diff --git a/.DS_Store b/.DS_Store
index bbe19d5b7d..ed48527ae5 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/h2db/weiyuim.mv.db b/h2db/weiyuim.mv.db
deleted file mode 100644
index 1c201e6250..0000000000
Binary files a/h2db/weiyuim.mv.db and /dev/null differ
diff --git a/modules/.DS_Store b/modules/.DS_Store
index 874ddc5f85..3463a3ffbf 100644
Binary files a/modules/.DS_Store and b/modules/.DS_Store differ
diff --git a/modules/ai/.DS_Store b/modules/ai/.DS_Store
index 8b8c75ae5d..4de17a5802 100644
Binary files a/modules/ai/.DS_Store and b/modules/ai/.DS_Store differ
diff --git a/modules/ai/pom.xml b/modules/ai/pom.xml
index adbda9208c..6dc9fcd2e1 100644
--- a/modules/ai/pom.xml
+++ b/modules/ai/pom.xml
@@ -17,42 +17,48 @@
- 0.8.1-SNAPSHOT
+
+ 1.0.0-SNAPSHOT
-
+
+
+
org.springframework.ai
spring-ai-ollama-spring-boot-starter
- ${spring-ai.version}
+
+
+
-
-
+
+
+ org.springframework.ai
+ spring-ai-zhipuai-spring-boot-starter
+
@@ -63,7 +69,35 @@
provided
+
+
+
+
+
+ cn.bigmodel.openapi
+ oapi-java-sdk
+ release-V4-2.1.0
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+ org.springframework.ai
+ spring-ai-bom
+ ${spring-ai.version}
+ pom
+ import
+
+
+
diff --git a/modules/ai/readme.md b/modules/ai/readme.md
index 2f5ca6cdf1..c64786dc8e 100644
--- a/modules/ai/readme.md
+++ b/modules/ai/readme.md
@@ -1,6 +1,24 @@
+
# ai
## docs
- [spring-ai](https://docs.spring.io/spring-ai/reference/)
- [spring-ai-github](https://github.com/spring-projects/spring-ai)
+
+```bash
+ollama --help
+```
diff --git a/modules/ai/src/.DS_Store b/modules/ai/src/.DS_Store
index 797ff1f11b..6378e6aadb 100644
Binary files a/modules/ai/src/.DS_Store and b/modules/ai/src/.DS_Store differ
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/doc/KbDoc.java b/modules/ai/src/main/java/com/bytedesk/ai/doc/KbDoc.java
index 5a9196cd4d..e3ed636b30 100644
--- a/modules/ai/src/main/java/com/bytedesk/ai/doc/KbDoc.java
+++ b/modules/ai/src/main/java/com/bytedesk/ai/doc/KbDoc.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-22 16:21:15
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-15 09:20:13
+ * @LastEditTime: 2024-05-27 11:59:13
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -16,6 +16,7 @@ package com.bytedesk.ai.doc;
import com.bytedesk.ai.file.KbFile;
import com.bytedesk.core.base.BaseEntity;
+import com.bytedesk.core.constant.TypeConsts;
import jakarta.persistence.Column;
import jakarta.persistence.ConstraintMode;
@@ -43,15 +44,12 @@ import lombok.experimental.Accessors;
@NoArgsConstructor
@Table(name = "ai_kb_doc")
public class KbDoc extends BaseEntity {
-
- private static final long serialVersionUID = 1L;
-
- // @Column(name = "did", unique = true, nullable = false)
- // private String did;
- @Column(columnDefinition = "LONGTEXT")
+ private static final long serialVersionUID = 1L;
+
+ @Column(columnDefinition = TypeConsts.COLUMN_TYPE_TEXT)
private String content;
-
+
private String meta;
/**
@@ -60,11 +58,20 @@ public class KbDoc extends BaseEntity {
@JoinColumn(name = "kb_file_id", foreignKey = @ForeignKey(name = "none", value = ConstraintMode.NO_CONSTRAINT))
private KbFile kbFile;
+ /**
+ * belong to org
+ */
+ // @JsonIgnore
+ // @ManyToOne(fetch = FetchType.LAZY)
+ // private Organization organization;
+ private String orgUid;
+
/**
* 所属用户
*/
// @JsonIgnore
// @ManyToOne(fetch = FetchType.LAZY)
- // @JoinColumn(name = "user_id", foreignKey = @ForeignKey(name = "none", value = ConstraintMode.NO_CONSTRAINT))
+ // @JoinColumn(name = "user_id", foreignKey = @ForeignKey(name = "none", value =
+ // ConstraintMode.NO_CONSTRAINT))
// private User user;
}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/doc/KbDocController.java b/modules/ai/src/main/java/com/bytedesk/ai/doc/KbDocController.java
index 7a5b93c7b4..12d553a0f4 100644
--- a/modules/ai/src/main/java/com/bytedesk/ai/doc/KbDocController.java
+++ b/modules/ai/src/main/java/com/bytedesk/ai/doc/KbDocController.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-22 16:59:55
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-08 09:15:09
+ * @LastEditTime: 2024-05-31 07:40:45
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -14,14 +14,13 @@
*/
package com.bytedesk.ai.doc;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-import com.bytedesk.core.utils.JsonResult;
+import com.bytedesk.core.base.BaseController;
+import io.swagger.v3.oas.annotations.parameters.RequestBody;
import lombok.AllArgsConstructor;
/**
@@ -30,74 +29,39 @@ import lombok.AllArgsConstructor;
@RestController
@RequestMapping("/api/v1/kb/doc")
@AllArgsConstructor
-public class KbDocController {
+public class KbDocController extends BaseController {
private final KbDocService kbDocService;
- /**
- * query
- *
- * @param kbDocRequest
- * @return
- */
- @GetMapping("/query")
- public JsonResult> query(KbDocRequest kbDocRequest) {
-
- return JsonResult.success(kbDocService.query(kbDocRequest));
+ @Override
+ public ResponseEntity> queryByOrg(KbDocRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'queryByOrg'");
}
- /**
- * create
- *
- * @param kbDocRequest kb
- * @return json
- */
- @PostMapping("/create")
- public JsonResult> create(@RequestBody KbDocRequest kbDocRequest) {
-
- // return kbService.create(kbDocRequest);
- return JsonResult.success();
+ @Override
+ public ResponseEntity> query(KbDocRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'query'");
}
- /**
- * update
- *
- * @param kbDocRequest kb
- * @return json
- */
- @PostMapping("/update")
- public JsonResult> update(@RequestBody KbDocRequest kbDocRequest) {
-
- //
- return new JsonResult<>("update success", 200, false);
+ @Override
+ public ResponseEntity> create(@RequestBody KbDocRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'create'");
}
- /**
- * delete
- *
- * @param kbDocRequest kb
- * @return json
- */
- @PostMapping("/delete")
- public JsonResult> delete(@RequestBody KbDocRequest kbDocRequest) {
-
- //
-
- return new JsonResult<>("delete success", 200, true);
+ @Override
+ public ResponseEntity> update(@RequestBody KbDocRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'update'");
}
- /**
- * filter
- *
- * @return json
- */
- @GetMapping("/filter")
- public JsonResult> filter(KbDocRequest filterParam) {
-
- //
-
- //
- return new JsonResult<>("filter success", 200, false);
+ @Override
+ public ResponseEntity> delete(@RequestBody KbDocRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'delete'");
}
+
}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/doc/KbDocService.java b/modules/ai/src/main/java/com/bytedesk/ai/doc/KbDocService.java
index 44c5f27953..784bb3107d 100644
--- a/modules/ai/src/main/java/com/bytedesk/ai/doc/KbDocService.java
+++ b/modules/ai/src/main/java/com/bytedesk/ai/doc/KbDocService.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-22 17:00:07
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-04 10:55:40
+ * @LastEditTime: 2024-05-27 11:55:19
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -14,36 +14,98 @@
*/
package com.bytedesk.ai.doc;
-import org.modelmapper.ModelMapper;
+import java.util.Optional;
+
import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageRequest;
-import org.springframework.data.domain.Pageable;
-import org.springframework.data.domain.Sort;
+import org.springframework.orm.ObjectOptimisticLockingFailureException;
import org.springframework.stereotype.Service;
+import com.bytedesk.core.base.BaseService;
+
import lombok.AllArgsConstructor;
@Service
@AllArgsConstructor
-public class KbDocService {
+public class KbDocService extends BaseService {
- private final KbDocRepository kbDocRepository;
+ // private final KbDocRepository kbDocRepository;
- private final ModelMapper modelMapper;
+ // private final ModelMapper modelMapper;
- public Page query(KbDocRequest kbDocRequest) {
-
- Pageable pageable = PageRequest.of(kbDocRequest.getPageNumber(), kbDocRequest.getPageSize(),
- Sort.Direction.DESC,
- "id");
-
- Page kbDocPage = kbDocRepository.findAll(pageable);
-
- return kbDocPage.map(this::convertToDocResponse);
+ @Override
+ public Page queryByOrg(KbDocRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'queryByOrg'");
}
+
+ @Override
+ public Page queryByUser(KbDocRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'queryByUser'");
+ }
+
+ @Override
+ public Optional findByUid(String uid) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'findByUid'");
+ }
+
+ @Override
+ public KbDocResponse create(KbDocRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'create'");
+ }
+
+ @Override
+ public KbDocResponse update(KbDocRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'update'");
+ }
+
+ @Override
+ public KbDoc save(KbDoc entity) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'save'");
+ }
+
+ @Override
+ public void deleteByUid(String uid) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'deleteByUid'");
+ }
+
+ @Override
+ public void delete(KbDoc entity) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'delete'");
+ }
+
+ @Override
+ public void handleOptimisticLockingFailureException(ObjectOptimisticLockingFailureException e, KbDoc entity) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'handleOptimisticLockingFailureException'");
+ }
+
+ @Override
+ public KbDocResponse convertToResponse(KbDoc entity) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'convertToResponse'");
+ }
+
- public KbDocResponse convertToDocResponse(KbDoc kbDoc) {
- return modelMapper.map(kbDoc, KbDocResponse.class);
- }
+ // public Page query(KbDocRequest kbDocRequest) {
+
+ // Pageable pageable = PageRequest.of(kbDocRequest.getPageNumber(), kbDocRequest.getPageSize(),
+ // Sort.Direction.DESC,
+ // "id");
+
+ // Page kbDocPage = kbDocRepository.findAll(pageable);
+
+ // return kbDocPage.map(this::convertToDocResponse);
+ // }
+
+ // public KbDocResponse convertToDocResponse(KbDoc kbDoc) {
+ // return modelMapper.map(kbDoc, KbDocResponse.class);
+ // }
}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/file/KbFile.java b/modules/ai/src/main/java/com/bytedesk/ai/file/KbFile.java
index 811a6390ae..a2094a0ed7 100644
--- a/modules/ai/src/main/java/com/bytedesk/ai/file/KbFile.java
+++ b/modules/ai/src/main/java/com/bytedesk/ai/file/KbFile.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-22 16:23:35
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-04 10:56:57
+ * @LastEditTime: 2024-05-27 11:59:22
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -49,18 +49,12 @@ public class KbFile extends BaseEntity {
private static final long serialVersionUID = 1L;
- // @Column(name = "fid", unique = true, nullable = false)
- // private String fid;
-
private String loader;
private String splitter;
private Integer docsCount;
- /**
- *
- */
@JoinColumn(name = "upload_id", foreignKey = @ForeignKey(name = "none", value = ConstraintMode.NO_CONSTRAINT))
private Upload upload;
@@ -72,6 +66,14 @@ public class KbFile extends BaseEntity {
@JoinColumn(name = "kb_id", foreignKey = @ForeignKey(name = "none", value = ConstraintMode.NO_CONSTRAINT))
private Kb kb;
+ /**
+ * belong to org
+ */
+ // @JsonIgnore
+ // @ManyToOne(fetch = FetchType.LAZY)
+ // private Organization organization;
+ private String orgUid;
+
/**
* 所属用户
*/
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/file/KbFileController.java b/modules/ai/src/main/java/com/bytedesk/ai/file/KbFileController.java
index 9ed4c45414..ae5cbfc92a 100644
--- a/modules/ai/src/main/java/com/bytedesk/ai/file/KbFileController.java
+++ b/modules/ai/src/main/java/com/bytedesk/ai/file/KbFileController.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-22 16:48:26
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-08 09:15:24
+ * @LastEditTime: 2024-05-31 07:40:57
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -14,14 +14,13 @@
*/
package com.bytedesk.ai.file;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-import com.bytedesk.core.utils.JsonResult;
+import com.bytedesk.core.base.BaseController;
+import io.swagger.v3.oas.annotations.parameters.RequestBody;
import lombok.AllArgsConstructor;
/**
@@ -30,74 +29,40 @@ import lombok.AllArgsConstructor;
@RestController
@RequestMapping("/api/v1/kb/file")
@AllArgsConstructor
-public class KbFileController {
+public class KbFileController extends BaseController {
private final KbFileService kbService;
- /**
- * query
- *
- * @param kbFileRequest
- * @return
- */
- @GetMapping("/query")
- public JsonResult> query(KbFileRequest kbFileRequest) {
-
- return JsonResult.success(kbService.query(kbFileRequest));
+ @Override
+ public ResponseEntity> queryByOrg(KbFileRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'queryByOrg'");
}
- /**
- * create
- *
- * @param kbFileRequest kb
- * @return json
- */
- @PostMapping("/create")
- public JsonResult> create(@RequestBody KbFileRequest kbFileRequest) {
-
- // return kbService.create(kbFileRequest);
- return JsonResult.success();
+ @Override
+ public ResponseEntity> query(KbFileRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'query'");
}
- /**
- * update
- *
- * @param kbFileRequest kb
- * @return json
- */
- @PostMapping("/update")
- public JsonResult> update(@RequestBody KbFileRequest kbFileRequest) {
-
- //
- return new JsonResult<>("update success", 200, false);
+ @Override
+ public ResponseEntity> create(@RequestBody KbFileRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'create'");
}
- /**
- * delete
- *
- * @param kbFileRequest kb
- * @return json
- */
- @PostMapping("/delete")
- public JsonResult> delete(@RequestBody KbFileRequest kbFileRequest) {
-
- //
-
- return new JsonResult<>("delete success", 200, true);
+ @Override
+ public ResponseEntity> update(@RequestBody KbFileRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'update'");
}
- /**
- * filter
- *
- * @return json
- */
- @GetMapping("/filter")
- public JsonResult> filter(KbFileRequest filterParam) {
-
- //
-
- //
- return new JsonResult<>("filter success", 200, false);
+ @Override
+ public ResponseEntity> delete(@RequestBody KbFileRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'delete'");
}
+
+
}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/kb/Kb.java b/modules/ai/src/main/java/com/bytedesk/ai/kb/Kb.java
index 3094893845..9bd44ba7cf 100644
--- a/modules/ai/src/main/java/com/bytedesk/ai/kb/Kb.java
+++ b/modules/ai/src/main/java/com/bytedesk/ai/kb/Kb.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-22 16:13:38
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-04 10:58:05
+ * @LastEditTime: 2024-06-11 11:41:42
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -15,6 +15,7 @@
package com.bytedesk.ai.kb;
import com.bytedesk.core.base.BaseEntity;
+import com.bytedesk.core.constant.I18Consts;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
@@ -41,9 +42,6 @@ public class Kb extends BaseEntity {
private static final long serialVersionUID = 1L;
- // @Column(name = "kid", unique = true, nullable = false)
- // private String kid;
-
private String name;
private String vectorStore;
@@ -51,8 +49,20 @@ public class Kb extends BaseEntity {
private String embeddings;
// is_published or not
- // private boolean published;
+ @Builder.Default
+ private boolean published = true;
+ @Builder.Default
+ private String language = I18Consts.ZH_CN;
+
+ /**
+ * belong to org
+ */
+ // @JsonIgnore
+ // @ManyToOne(fetch = FetchType.LAZY)
+ // private Organization organization;
+ private String orgUid;
+
/**
* 所属用户
*/
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/kb/KbController.java b/modules/ai/src/main/java/com/bytedesk/ai/kb/KbController.java
index bc14399beb..1d4a7a61a0 100644
--- a/modules/ai/src/main/java/com/bytedesk/ai/kb/KbController.java
+++ b/modules/ai/src/main/java/com/bytedesk/ai/kb/KbController.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-22 16:46:14
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-08 09:15:35
+ * @LastEditTime: 2024-05-31 07:41:03
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -14,14 +14,13 @@
*/
package com.bytedesk.ai.kb;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-import com.bytedesk.core.utils.JsonResult;
+import com.bytedesk.core.base.BaseController;
+import io.swagger.v3.oas.annotations.parameters.RequestBody;
import lombok.AllArgsConstructor;
/**
@@ -30,73 +29,39 @@ import lombok.AllArgsConstructor;
@RestController
@RequestMapping("/api/v1/kb")
@AllArgsConstructor
-public class KbController {
+public class KbController extends BaseController {
private final KbService kbService;
- /**
- * query
- *
- * @param kbRequest
- * @return
- */
- @GetMapping("/query")
- public JsonResult> query(KbRequest kbRequest) {
-
- return JsonResult.success(kbService.query(kbRequest));
+ @Override
+ public ResponseEntity> queryByOrg(KbRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'queryByOrg'");
}
- /**
- * create
- *
- * @param kbRequest kb
- * @return json
- */
- @PostMapping("/create")
- public JsonResult> create(@RequestBody KbRequest kbRequest) {
-
- return kbService.create(kbRequest);
+ @Override
+ public ResponseEntity> query(KbRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'query'");
}
- /**
- * update
- *
- * @param kbRequest kb
- * @return json
- */
- @PostMapping("/update")
- public JsonResult> update(@RequestBody KbRequest kbRequest) {
-
- //
- return new JsonResult<>("update success", 200, false);
+ @Override
+ public ResponseEntity> create(@RequestBody KbRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'create'");
}
- /**
- * delete
- *
- * @param kbRequest kb
- * @return json
- */
- @PostMapping("/delete")
- public JsonResult> delete(@RequestBody KbRequest kbRequest) {
-
- //
-
- return new JsonResult<>("delete success", 200, true);
+ @Override
+ public ResponseEntity> update(@RequestBody KbRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'update'");
}
- /**
- * filter
- *
- * @return json
- */
- @GetMapping("/filter")
- public JsonResult> filter(KbRequest filterParam) {
-
- //
-
- //
- return new JsonResult<>("filter success", 200, false);
+ @Override
+ public ResponseEntity> delete(@RequestBody KbRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'delete'");
}
+
}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/kb/KbService.java b/modules/ai/src/main/java/com/bytedesk/ai/kb/KbService.java
index 79347c0884..64936e14ee 100644
--- a/modules/ai/src/main/java/com/bytedesk/ai/kb/KbService.java
+++ b/modules/ai/src/main/java/com/bytedesk/ai/kb/KbService.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-22 16:46:24
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-04 10:58:11
+ * @LastEditTime: 2024-05-27 14:48:36
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -61,13 +61,14 @@ public class KbService {
return modelMapper.map(kb, KbResponse.class);
}
- public Kb getKb(String name) {
+ public Kb getKb(String name, String orgUid) {
Kb kb = Kb.builder()
// .kid(uidUtils.getCacheSerialUid())
.name(name)
.vectorStore("redis")
.embeddings("m3e-base")
+ .orgUid(orgUid)
.build();
kb.setUid(uidUtils.getCacheSerialUid());
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/llm/LlmService.java b/modules/ai/src/main/java/com/bytedesk/ai/llm/LlmService.java
deleted file mode 100644
index 078fbbb23f..0000000000
--- a/modules/ai/src/main/java/com/bytedesk/ai/llm/LlmService.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * @Author: jackning 270580156@qq.com
- * @Date: 2024-03-25 12:08:16
- * @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-04 10:59:23
- * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
- * Please be aware of the BSL license restrictions before installing Bytedesk IM –
- * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
- * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
- * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
- * contact: 270580156@qq.com
- * 联系:270580156@qq.com
- * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
- */
-package com.bytedesk.ai.llm;
-import org.springframework.stereotype.Service;
-
-import com.bytedesk.core.uid.UidUtils;
-import com.bytedesk.core.utils.JsonResult;
-
-import lombok.AllArgsConstructor;
-
-@Service
-@AllArgsConstructor
-public class LlmService {
-
- private LlmRepository llmRepository;
-
- private final UidUtils uidUtils;
-
- public JsonResult> create(LlmRequest llmRequest) {
-
-
- return JsonResult.success();
- }
-
- public Llm getLlm(String type) {
- Llm llm = new Llm();
- llm.setUid(uidUtils.getCacheSerialUid());
- llm.setName("智谱AI");
- llm.setDescription("对接智谱API");
- llm.setType(type);
- llm.setEmbeddings("m3e-base");
- llm.setTopK(3);
- llm.setTemperature(0.9);
- llm.setScoreThreshold(0.5);
- llm.setPrompt("你是一个聪明、对人类有帮助的人工智能,你可以对人类提出的问题给出有用、详细、礼貌的回答");
- return llmRepository.save(llm);
- }
-
- public void initData() {
-
- if (llmRepository.count() > 0) {
- return;
- }
- //
- getLlm("system");
- }
-
-
-}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/ollama/OllamaConfig.java b/modules/ai/src/main/java/com/bytedesk/ai/ollama/OllamaConfig.java
new file mode 100644
index 0000000000..3691d700ff
--- /dev/null
+++ b/modules/ai/src/main/java/com/bytedesk/ai/ollama/OllamaConfig.java
@@ -0,0 +1,59 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-05-31 10:24:39
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-05-31 11:11:28
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.ai.ollama;
+
+import org.springframework.ai.chat.client.ChatClient;
+import org.springframework.ai.ollama.OllamaChatModel;
+import org.springframework.ai.ollama.OllamaEmbeddingModel;
+import org.springframework.ai.ollama.api.OllamaApi;
+import org.springframework.ai.ollama.api.OllamaOptions;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * https://docs.spring.io/spring-ai/reference/api/embeddings/ollama-embeddings.html
+ */
+@Configuration
+public class OllamaConfig {
+
+ @Bean
+ OllamaApi ollamaApi() {
+ return new OllamaApi("http://localhost:11434");
+ }
+
+ // https://docs.spring.io/spring-ai/reference/api/chatclient.html
+ @Bean
+ ChatClient chatClient(ChatClient.Builder builder) {
+ return builder.defaultSystem("You are a friendly chat bot that answers question")
+ .build();
+ }
+
+ @Bean
+ OllamaChatModel chatModel() {
+ return new OllamaChatModel(ollamaApi(),
+ OllamaOptions.create()
+ // .withModel(OllamaOptions.DEFAULT_MODEL)
+ .withModel("qwen:7b")
+ .withTemperature(0.9f));
+ }
+
+ // https://docs.spring.io/spring-ai/reference/api/embeddings/ollama-embeddings.html
+ @Bean
+ OllamaEmbeddingModel ollamaEmbeddingModel() {
+ return new OllamaEmbeddingModel(ollamaApi());
+ }
+
+
+}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/ollama/OllamaController.java b/modules/ai/src/main/java/com/bytedesk/ai/ollama/OllamaController.java
new file mode 100644
index 0000000000..854ead9116
--- /dev/null
+++ b/modules/ai/src/main/java/com/bytedesk/ai/ollama/OllamaController.java
@@ -0,0 +1,99 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-05-31 09:50:56
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-05-31 11:12:19
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.ai.ollama;
+
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.ai.chat.client.ChatClient;
+import org.springframework.ai.chat.messages.UserMessage;
+import org.springframework.ai.chat.model.ChatResponse;
+import org.springframework.ai.chat.prompt.Prompt;
+import org.springframework.ai.embedding.EmbeddingRequest;
+import org.springframework.ai.embedding.EmbeddingResponse;
+import org.springframework.ai.ollama.OllamaChatModel;
+import org.springframework.ai.ollama.OllamaEmbeddingModel;
+import org.springframework.ai.ollama.api.OllamaOptions;
+import org.springframework.http.ResponseEntity;
+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 com.bytedesk.core.utils.JsonResult;
+
+import lombok.AllArgsConstructor;
+import reactor.core.publisher.Flux;
+
+// https://docs.spring.io/spring-ai/reference/api/chat/ollama-chat.html
+@RestController
+@RequestMapping("/visitor/api/v1/ai/ollama")
+@AllArgsConstructor
+public class OllamaController {
+
+ private final OllamaEmbeddingModel ollamaEmbeddingModel;
+
+ private final ChatClient chatClient;
+
+ private final OllamaChatModel chatModel;
+
+ // public OllamaController(EmbeddingModel embeddingModel, ChatClient.Builder chatClientbBuilder) {
+ // this.embeddingModel = embeddingModel;
+ // this.chatClient = chatClientbBuilder.build();
+ // }
+
+ // http://localhost:9003/visitor/api/v1/ai/ollama/chat?input=hello
+ @GetMapping("/chat")
+ public ResponseEntity> generation(@RequestParam("input") String input) {
+ String content = this.chatClient.prompt()
+ .user(input)
+ .call()
+ .content();
+ return ResponseEntity.ok(JsonResult.success(content));
+ }
+
+ // http://localhost:9003/visitor/api/v1/ai/ollama/simple
+ @GetMapping("/simple")
+ public Map completion(
+ @RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
+ return Map.of("completion", chatClient.prompt().user(message).call().content());
+ }
+
+ // http://localhost:9003/visitor/api/v1/ai/ollama/generate
+ @GetMapping("/generate")
+ public Map, ?> generate(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
+ return Map.of("generation", chatModel.call(message));
+ }
+
+ // http://localhost:9003/visitor/api/v1/ai/ollama/generateStream
+ @GetMapping("/generateStream")
+ public Flux generateStream(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
+ Prompt prompt = new Prompt(new UserMessage(message));
+ return chatModel.stream(prompt);
+ }
+
+ /*
+ * http://localhost:9003/visitor/api/v1/ai/ollama/embedding
+ */
+ @GetMapping("/embedding")
+ public Map, ?> embed(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
+ // EmbeddingResponse embeddingResponse = embeddingModel.embedForResponse(List.of(message));
+ //
+ EmbeddingResponse embeddingResponse = ollamaEmbeddingModel.call(new EmbeddingRequest(List.of("Hello World", "World is big and salvation is near"),
+ OllamaOptions.create().withModel("qwen:7b")));
+
+ return Map.of("embedding", embeddingResponse);
+ }
+}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/robot/Robot.java b/modules/ai/src/main/java/com/bytedesk/ai/robot/Robot.java
index 2e04155e53..b2ff1f2bd4 100644
--- a/modules/ai/src/main/java/com/bytedesk/ai/robot/Robot.java
+++ b/modules/ai/src/main/java/com/bytedesk/ai/robot/Robot.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-22 16:16:26
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-04 10:59:40
+ * @LastEditTime: 2024-06-12 07:19:14
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -15,14 +15,19 @@
package com.bytedesk.ai.robot;
import com.bytedesk.ai.kb.Kb;
-import com.bytedesk.ai.llm.Llm;
import com.bytedesk.core.base.BaseEntity;
-import com.bytedesk.core.rbac.user.User;
+import com.bytedesk.core.constant.AvatarConsts;
+import com.bytedesk.core.constant.I18Consts;
+import com.bytedesk.core.constant.TypeConsts;
import com.fasterxml.jackson.annotation.JsonIgnore;
+// import jakarta.persistence.AssociationOverride;
+// import jakarta.persistence.AssociationOverrides;
import jakarta.persistence.Column;
import jakarta.persistence.ConstraintMode;
+import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
+import jakarta.persistence.EntityListeners;
import jakarta.persistence.FetchType;
import jakarta.persistence.ForeignKey;
import jakarta.persistence.JoinColumn;
@@ -47,36 +52,46 @@ import lombok.experimental.Accessors;
@EqualsAndHashCode(callSuper = true)
@AllArgsConstructor
@NoArgsConstructor
+@EntityListeners({ RobotEntityListener.class })
@Table(name = "ai_robot")
public class Robot extends BaseEntity {
private static final long serialVersionUID = 1L;
- // @Column(name = "rid", unique = true, nullable = false)
- // private String rid;
+ private String nickname;
- private String name;
-
- private String avatar;
+ @Builder.Default
+ private String avatar = AvatarConsts.DEFAULT_AVATAR_URL;
- private String description;
+ @Builder.Default
+ private String description = I18Consts.I18N_ROBOT_DESCRIPTION;
- private String welcome;
+ @Embedded
+ @Builder.Default
+ private RobotServiceSettings serviceSettings = new RobotServiceSettings();
+
+ @Embedded
+ @Builder.Default
+ private RobotLlm llm = new RobotLlm();
// 客服机器人、问答机器人、闲聊
// service、ask、chat
- @Column(name = "by_type")
- private String type;
+ @Builder.Default
+ @Column(name = TypeConsts.COLUMN_NAME_TYPE)
+ // private String type = TypeConsts.ROBOT_TYPE_SERVICE;
+ private RobotTypeEnum type = RobotTypeEnum.SERVICE;
// is_published or not
- private boolean published;
-
- /**
- * llm
- */
- @ManyToOne()
- @JoinColumn(name = "llm_id", foreignKey = @ForeignKey(name = "none", value = ConstraintMode.NO_CONSTRAINT))
- private Llm llm;
+ @Builder.Default
+ private boolean published = false;
+
+ // /**
+ // * llm
+ // */
+ // @ManyToOne()
+ // @JoinColumn(name = "llm_id", foreignKey = @ForeignKey(name = "none", value =
+ // ConstraintMode.NO_CONSTRAINT))
+ // private Llm llm;
/**
* 知识库
@@ -87,10 +102,13 @@ public class Robot extends BaseEntity {
private Kb kb;
/**
- * 所属用户
+ * belong to org
*/
- @JsonIgnore
- @ManyToOne(fetch = FetchType.LAZY)
- @JoinColumn(name = "user_id", foreignKey = @ForeignKey(name = "none", value = ConstraintMode.NO_CONSTRAINT))
- private User user;
+ // @JsonIgnore
+ // @ManyToOne(fetch = FetchType.LAZY)
+ // private Organization organization;
+ private String orgUid;
+
+
+
}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotController.java b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotController.java
index fd690fd374..8ccdc2fb3d 100644
--- a/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotController.java
+++ b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotController.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-22 16:37:01
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-08 09:15:46
+ * @LastEditTime: 2024-06-05 10:19:17
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -14,14 +14,18 @@
*/
package com.bytedesk.ai.robot;
+import org.springframework.data.domain.Page;
+import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
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;
+import com.bytedesk.core.action.ActionAnnotation;
+import com.bytedesk.core.base.BaseController;
import com.bytedesk.core.utils.JsonResult;
+import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
@@ -32,74 +36,54 @@ import lombok.AllArgsConstructor;
@RequestMapping("/api/v1/robot")
@AllArgsConstructor
@Tag(name = "robot - 机器人", description = "robot description")
-public class RobotController {
+public class RobotController extends BaseController {
private final RobotService robotService;
- /**
- * query
- *
- * @param robotRequest
- * @return
- */
- @GetMapping("/query")
- public JsonResult> query(RobotRequest robotRequest) {
-
- return JsonResult.success(robotService.query(robotRequest));
- }
-
- /**
- * create
- *
- * @param robotRequest robot
- * @return json
- */
- @PostMapping("/create")
- public JsonResult> create(@RequestBody RobotRequest robotRequest) {
-
- return robotService.create(robotRequest);
- }
-
- /**
- * update
- *
- * @param robotRequest robot
- * @return json
- */
- @PostMapping("/update")
- public JsonResult> update(@RequestBody RobotRequest robotRequest) {
-
- //
- return new JsonResult<>("update success", 200, false);
- }
-
- /**
- * delete
- *
- * @param robotRequest robot
- * @return json
- */
- @PostMapping("/delete")
- public JsonResult> delete(@RequestBody RobotRequest robotRequest) {
-
- //
-
- return new JsonResult<>("delete success", 200, true);
- }
-
- /**
- * filter
- *
- * @return json
- */
- @GetMapping("/filter")
- public JsonResult> filter(RobotRequest filterParam) {
-
- //
+ @GetMapping("/query/org")
+ @Override
+ public ResponseEntity> queryByOrg(RobotRequest request) {
- //
- return new JsonResult<>("filter success", 200, false);
+ Page page = robotService.queryByOrg(request);
+
+ return ResponseEntity.ok(JsonResult.success(page));
}
+ @GetMapping("/query/user")
+ @Override
+ public ResponseEntity> query(RobotRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'query'");
+ }
+
+ @ActionAnnotation(title = "robot", action = "create", description = "create robot")
+ @PostMapping("/create")
+ @Override
+ public ResponseEntity> create(@RequestBody RobotRequest request) {
+
+ RobotResponse robot = robotService.create(request);
+
+ return ResponseEntity.ok(JsonResult.success(robot));
+ }
+
+ @ActionAnnotation(title = "robot", action = "update", description = "update robot")
+ @PostMapping("/update")
+ @Override
+ public ResponseEntity> update(@RequestBody RobotRequest request) {
+
+ RobotResponse robotResponse = robotService.update(request);
+
+ return ResponseEntity.ok(JsonResult.success(robotResponse));
+ }
+
+ @ActionAnnotation(title = "robot", action = "delete", description = "delete robot")
+ @PostMapping("/delete")
+ @Override
+ public ResponseEntity> delete(@RequestBody RobotRequest request) {
+
+ robotService.deleteByUid(request.getUid());
+
+ return ResponseEntity.ok(JsonResult.success(request));
+ }
}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotEmbedingEnum.java b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotEmbedingEnum.java
new file mode 100644
index 0000000000..489272f341
--- /dev/null
+++ b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotEmbedingEnum.java
@@ -0,0 +1,47 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-06-06 13:08:36
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-06 13:08:39
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.ai.robot;
+
+public enum RobotEmbedingEnum {
+ M3E_BASE("m3e-base");
+
+
+ // private final String name;
+ private final String value;
+
+ RobotEmbedingEnum(String value) {
+ // this.name = name;
+ this.value = value;
+ }
+
+ // public String getName() {
+ // return name;
+ // }
+
+ // 获取枚举常量的整型值
+ public String getValue() {
+ return value;
+ }
+
+ // 根据整型值查找对应的枚举常量
+ public static RobotEmbedingEnum fromValue(String value) {
+ for (RobotEmbedingEnum type : RobotEmbedingEnum.values()) {
+ if (type.getValue().equalsIgnoreCase(value)) {
+ return type;
+ }
+ }
+ throw new IllegalArgumentException("No RobotEmbedingEnum constant with value " + value);
+ }
+}
diff --git a/modules/service/src/main/java/com/bytedesk/service/customer/CustomerSummary.java b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotEntityListener.java
similarity index 66%
rename from modules/service/src/main/java/com/bytedesk/service/customer/CustomerSummary.java
rename to modules/ai/src/main/java/com/bytedesk/ai/robot/RobotEntityListener.java
index f8bffacbe9..333e748395 100644
--- a/modules/service/src/main/java/com/bytedesk/service/customer/CustomerSummary.java
+++ b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotEntityListener.java
@@ -1,8 +1,8 @@
/*
* @Author: jackning 270580156@qq.com
- * @Date: 2024-04-12 15:06:27
+ * @Date: 2024-06-12 07:17:00
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-04-12 15:09:56
+ * @LastEditTime: 2024-06-12 07:22:52
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -12,16 +12,18 @@
* 联系:270580156@qq.com
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
*/
-package com.bytedesk.service.customer;
+package com.bytedesk.ai.robot;
-/**
- * https://docs.spring.io/spring-data/jpa/reference/repositories/projections.html
- */
-public interface CustomerSummary {
- String getName();
- AddressSummary getAddress();
+import org.springframework.stereotype.Component;
- interface AddressSummary {
- String getCity();
+import jakarta.persistence.PostPersist;
+
+@Component
+public class RobotEntityListener {
+
+ @PostPersist
+ public void onPostPersist(Robot robot) {
+ System.out.println("RobotListener: onPostPersist");
}
+
}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotEventListener.java b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotEventListener.java
new file mode 100644
index 0000000000..333e45a99c
--- /dev/null
+++ b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotEventListener.java
@@ -0,0 +1,71 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-06-12 07:17:13
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-12 09:45:24
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.ai.robot;
+
+import org.springframework.context.event.EventListener;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+import com.bytedesk.ai.kb.Kb;
+import com.bytedesk.ai.kb.KbService;
+import com.bytedesk.core.constant.AvatarConsts;
+import com.bytedesk.core.constant.I18Consts;
+import com.bytedesk.core.rbac.organization.Organization;
+import com.bytedesk.core.rbac.organization.OrganizationCreateEvent;
+// import com.bytedesk.core.rbac.user.User;
+import com.bytedesk.core.uid.UidUtils;
+
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@Component
+@AllArgsConstructor
+public class RobotEventListener {
+
+ private final RobotService robotService;
+
+ private final KbService kbService;
+
+ private final UidUtils uidUtils;
+
+ @Order(2)
+ @EventListener
+ public void onOrganizationCreateEvent(OrganizationCreateEvent event) {
+ Organization organization = (Organization) event.getSource();
+ // User user = organization.getUser();
+ log.info("robot - organization created: {}", organization.getName());
+ //
+ Kb kb = kbService.getKb(I18Consts.I18N_ROBOT_NICKNAME, organization.getUid());
+ RobotLlm llm = RobotLlm.builder().build();
+
+ Robot robot = Robot.builder()
+ // .nickname(I18Consts.I18N_ROBOT_NICKNAME)
+ .description(I18Consts.I18N_ROBOT_DESCRIPTION)
+ .type(RobotTypeEnum.SERVICE)
+ .orgUid(organization.getUid())
+ .kb(kb)
+ .llm(llm)
+ .build();
+ robot.setUid(uidUtils.getCacheSerialUid());
+ robot.setNickname(I18Consts.I18N_ROBOT_NICKNAME);
+ robot.setAvatar(AvatarConsts.DEFAULT_AVATAR_URL);
+ //
+ robotService.save(robot);
+ }
+
+
+
+}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotLlm.java b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotLlm.java
new file mode 100644
index 0000000000..c13498a3ce
--- /dev/null
+++ b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotLlm.java
@@ -0,0 +1,72 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-06-05 10:02:51
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-11 11:52:16
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.ai.robot;
+
+import com.bytedesk.core.constant.I18Consts;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+// https://docs.spring.io/spring-data/jpa/reference/repositories/projections.html
+@Embeddable
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class RobotLlm {
+
+ // 默认不起用llm问答,需要管理后台手动启动
+ @Builder.Default
+ @Column(name = "is_enabled")
+ private boolean enabled = false;
+
+ @Builder.Default
+ private int topK = 3;
+
+ @Builder.Default
+ private Double scoreThreshold = 0.5;
+
+ @Builder.Default
+ private RobotModelEnum model = RobotModelEnum.ZHIPUAI_GLM_3_TURBO;
+
+ @Builder.Default
+ // private String embeddings = "m3e-base";
+ private RobotEmbedingEnum embeddings = RobotEmbedingEnum.M3E_BASE;
+
+ @Builder.Default
+ private Float temperature = 0.9f;
+
+ @Builder.Default
+ private Float topP = 0.7f;
+
+ @Builder.Default
+ private String prompt = I18Consts.I18N_ROBOT_LLM_PROMPT_ZH_CN;
+
+ // 默认是true,表示使用自定义模型, false表示云服务(需要在配置文件中配置相关参数)
+ @Builder.Default
+ @Column(name = "is_custom")
+ private boolean custom = true;
+
+ private String apiKey;
+
+ private String apiSecret;
+
+ private String apiUrl;
+
+}
\ No newline at end of file
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotMessage.java b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotMessage.java
new file mode 100644
index 0000000000..c3d355ffda
--- /dev/null
+++ b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotMessage.java
@@ -0,0 +1,53 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-06-05 12:41:13
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-06 12:09:38
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.ai.robot;
+
+import lombok.Builder;
+import lombok.Data;
+
+/**
+ * 转化为json存储到message表中content字段
+ * @{com.bytedesk.core.message.Message}
+ */
+@Data
+@Builder
+public class RobotMessage {
+ //
+ private String question;
+
+ private String answer;
+
+ public void clearAnswer() {
+ this.answer = "";
+ }
+
+ public void appendAnswer(String answer) {
+ this.answer += answer;
+ }
+
+ /**
+ * 参考:
+ * @{com.zhipu.oapi.service.v4.model.Usage}
+ */
+ @Builder.Default
+ private Integer promptTokens = 0;
+
+ @Builder.Default
+ private Integer completionTokens = 0;
+
+ @Builder.Default
+ private Integer totalTokens = 0;
+
+}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotModelEnum.java b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotModelEnum.java
new file mode 100644
index 0000000000..ffadcd8f1e
--- /dev/null
+++ b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotModelEnum.java
@@ -0,0 +1,61 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-06-05 10:42:05
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-06 13:12:14
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.ai.robot;
+
+public enum RobotModelEnum {
+ ZHIPUAI_GLM_3_TURBO("glm-3-turbo"),
+ ZHIPUAI_GLM_4("GLM-4"),
+ ZHIPUAI_CogView("cogview"),
+ ZHIPUAI_GLM4V("glm-4v"),
+ OLLAMA("ollama"),
+ OPENAI("openai");
+
+ // private final String name;
+ private final String value;
+
+ RobotModelEnum(String value) {
+ // this.name = name;
+ this.value = value;
+ }
+
+ // public String getName() {
+ // return name;
+ // }
+
+ // 获取枚举常量的整型值
+ public String getValue() {
+ return value;
+ }
+
+ // 根据整型值查找对应的枚举常量
+ public static RobotModelEnum fromValue(String value) {
+ for (RobotModelEnum type : RobotModelEnum.values()) {
+ if (type.getValue().equalsIgnoreCase(value)) {
+ return type;
+ }
+ }
+ throw new IllegalArgumentException("No RobotModelEnum constant with value " + value);
+ }
+
+ // public static RobotModelEnum fromString(String typeStr) {
+ // // 使用try-catch处理可能的异常
+ // try {
+ // return RobotModelEnum.valueOf(typeStr);
+ // } catch (IllegalArgumentException e) {
+ // // 处理错误,例如记录日志或抛出更具体的异常
+ // throw new IllegalArgumentException("Invalid robot type: " + typeStr, e);
+ // }
+ // }
+}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotRepository.java b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotRepository.java
index 8393a704a8..b1a802c90c 100644
--- a/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotRepository.java
+++ b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotRepository.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-22 16:44:54
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-03-26 15:12:12
+ * @LastEditTime: 2024-06-12 09:10:15
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -14,26 +14,25 @@
*/
package com.bytedesk.ai.robot;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.Pageable;
+import java.util.Optional;
+
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;
-import com.bytedesk.core.rbac.user.User;
-
import io.swagger.v3.oas.annotations.tags.Tag;
/**
- * 机器人
*
*/
@Repository
-@Tag(name = "robot info - 机器人")
+@Tag(name = "robot info")
// @PreAuthorize("hasRole('ROLE_ADMIN')")
public interface RobotRepository extends JpaRepository, JpaSpecificationExecutor {
-
- Page findByUser(User user, Pageable pageable);
- Boolean existsByUserAndName(User user, String name);
+ Optional findByUid(String uid);
+
+ // Page findByOrgUidAndDeleted(String orgUid, Boolean deleted, Pageable pageable);
+
+ Boolean existsByNicknameAndOrgUidAndDeleted(String nickname, String orgUid, Boolean deleted);
}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotRequest.java b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotRequest.java
index 003971fafc..1a840bbe13 100644
--- a/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotRequest.java
+++ b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotRequest.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-22 16:45:07
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-04-16 12:01:55
+ * @LastEditTime: 2024-06-11 12:27:10
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -16,6 +16,7 @@ package com.bytedesk.ai.robot;
import com.bytedesk.core.base.BaseRequest;
+import jakarta.validation.constraints.NotBlank;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -27,18 +28,24 @@ import lombok.experimental.Accessors;
@EqualsAndHashCode(callSuper = false)
public class RobotRequest extends BaseRequest {
- private String name;
+ private String nickname;
private String avatar;
private String description;
- private String welcome;
-
- // private boolean published;
+ // @Builder.Default
+ // private RobotTypeEnum type = RobotTypeEnum.SERVICE;
- //
+ @Builder.Default
+ private Boolean published = false;
+
+ @Builder.Default
+ private RobotServiceSettingsRequest serviceSettings = new RobotServiceSettingsRequest();
+
+ @Builder.Default
+ private RobotLlm llm = new RobotLlm();
-
-
+ @NotBlank
+ private String orgUid;
}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotResponse.java b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotResponse.java
index dc2b9edb43..6bf643de01 100644
--- a/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotResponse.java
+++ b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotResponse.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-22 16:45:18
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-04 10:59:48
+ * @LastEditTime: 2024-06-11 11:59:34
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -23,21 +23,24 @@ import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
-@EqualsAndHashCode(callSuper=false)
+@EqualsAndHashCode(callSuper = false)
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class RobotResponse extends BaseResponse {
- // private String rid;
-
- private String name;
-
+ private String nickname;
+
private String avatar;
private String description;
- private String welcome;
+ // private String type;
+ private RobotTypeEnum type;
- private boolean published;
+ private Boolean published;
+
+ private RobotServiceSettings serviceSettings;
+
+ private RobotLlm llm;
}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotResponseSimple.java b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotResponseSimple.java
new file mode 100644
index 0000000000..b751f316b5
--- /dev/null
+++ b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotResponseSimple.java
@@ -0,0 +1,27 @@
+package com.bytedesk.ai.robot;
+
+import com.bytedesk.core.base.BaseResponse;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+@Data
+@Builder
+@Accessors(chain = true)
+@AllArgsConstructor
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class RobotResponseSimple extends BaseResponse {
+
+ private static final long serialVersionUID = 1L;
+
+ private String nickname;
+
+ private String avatar;
+
+ private RobotLlm llm;
+}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotService.java b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotService.java
index c5e045e14a..39d75dc8c5 100644
--- a/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotService.java
+++ b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotService.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-22 16:44:41
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-04-17 23:57:32
+ * @LastEditTime: 2024-06-12 07:16:00
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -13,115 +13,200 @@
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.ai.robot;
+
+import java.util.Iterator;
import java.util.Optional;
import org.modelmapper.ModelMapper;
+import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
-import org.springframework.data.domain.Sort;
+import org.springframework.data.domain.Sort.Direction;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.orm.ObjectOptimisticLockingFailureException;
import org.springframework.stereotype.Service;
+import com.bytedesk.ai.kb.Kb;
import com.bytedesk.ai.kb.KbService;
-import com.bytedesk.ai.llm.LlmService;
+import com.bytedesk.core.base.BaseService;
import com.bytedesk.core.constant.AvatarConsts;
-import com.bytedesk.core.rbac.auth.AuthService;
-import com.bytedesk.core.rbac.user.User;
-import com.bytedesk.core.rbac.user.UserService;
+import com.bytedesk.core.constant.I18Consts;
+import com.bytedesk.core.constant.UserConsts;
+import com.bytedesk.core.quick_button.QuickButton;
+import com.bytedesk.core.quick_button.QuickButtonService;
import com.bytedesk.core.uid.UidUtils;
-import com.bytedesk.core.utils.JsonResult;
import lombok.AllArgsConstructor;
@Service
@AllArgsConstructor
-public class RobotService {
+public class RobotService extends BaseService {
private final RobotRepository robotRepository;
- private final AuthService authService;
-
- private final LlmService llmService;
-
private final KbService kbService;
- private final UserService userService;
+ private final QuickButtonService quickButtonService;
private final ModelMapper modelMapper;
private final UidUtils uidUtils;
- public Page query(RobotRequest robotRequest) {
+ @Override
+ public Page queryByOrg(RobotRequest request) {
- User user = authService.getCurrentUser();
-
- Pageable pageable = PageRequest.of(robotRequest.getPageNumber(), robotRequest.getPageSize(), Sort.Direction.DESC,
- "id");
- //
- Page robotPage = robotRepository.findByUser(user, pageable);
-
- return robotPage.map(robot -> modelMapper.map(robot, RobotResponse.class));
- }
-
- public JsonResult> create(RobotRequest robotRequest) {
-
- User user = authService.getCurrentUser();
-
- if (robotRepository.existsByUserAndName(user, robotRequest.getName())) {
- return JsonResult.error("机器人名称已存在");
- }
- //
- Robot robot = modelMapper.map(robotRequest, Robot.class);
- //
- String rid = uidUtils.getCacheSerialUid();
- robot.setUid(rid);
-
- robot.setAvatar(AvatarConsts.DEFAULT_AVATAR_URL);
- robot.setDescription("default robot description");
- robot.setWelcome("您好,有什么可以帮您的?");
- // robot.setType(null)
- robot.setPublished(false);
-
- robot.setLlm(llmService.getLlm("user"));
- robot.setKb(kbService.getKb(rid));
- robot.setUser(user);
-
- Robot result = robotRepository.save(robot);
-
- return JsonResult.success(result);
- }
-
-
- // @SuppressWarnings("null")
- public void initData() {
+ Pageable pageable = PageRequest.of(request.getPageNumber(), request.getPageSize(), Direction.ASC,
+ "updatedAt");
+ Specification specification = RobotSpecification.search(request);
+ Page page = robotRepository.findAll(specification, pageable);
+ // Page page = robotRepository.findByOrgUidAndDeleted(request.getOrgUid(), false, pageable);
+
+ return page.map(robot -> modelMapper.map(robot, RobotResponse.class));
+ }
+
+ @Override
+ public Page queryByUser(RobotRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'queryByUser'");
+ }
+
+ @Override
+ public RobotResponse create(RobotRequest request) {
+
+ if (existsByNicknameAndOrgUidAndDeleted(request.getNickname(), request.getOrgUid())) {
+ throw new RuntimeException("robot name already exists, please find another name");
+ }
+
+ Kb kb = kbService.getKb(request.getNickname(), request.getOrgUid());
+ RobotLlm llm = RobotLlm.builder().build();
+ //
+ Robot robot = Robot.builder()
+ // .nickname(request.getNickname())
+ .type(RobotTypeEnum.fromString(request.getType()))
+ .orgUid(request.getOrgUid())
+ .kb(kb)
+ .llm(llm)
+ .build();
+ robot.setUid(uidUtils.getCacheSerialUid());
+ robot.setNickname(request.getNickname());
+ robot.setAvatar(AvatarConsts.DEFAULT_AVATAR_URL);
+
+ return convertToResponse(save(robot));
+ }
+
+ @Override
+ public RobotResponse update(RobotRequest robotRequest) {
+
+ Optional robotOptional = findByUid(robotRequest.getUid());
+ if (!robotOptional.isPresent()) {
+ throw new RuntimeException("robot " + robotRequest.getUid() + " not found");
+ }
+ //
+ Robot robot = robotOptional.get();
+ robot.setNickname(robotRequest.getNickname());
+ robot.setAvatar(robotRequest.getAvatar());
+ robot.setDescription(robotRequest.getDescription());
+ robot.setPublished(robotRequest.getPublished());
+ //
+ // robot.setServiceSettings(request.getServiceSettings());
+ RobotServiceSettings serviceSettings = modelMapper.map(
+ robotRequest.getServiceSettings(), RobotServiceSettings.class);
+ if (robotRequest.getServiceSettings().getQuickButtonUids() != null
+ && robotRequest.getServiceSettings().getQuickButtonUids().size() > 0) {
+ Iterator iterator = robotRequest.getServiceSettings().getQuickButtonUids().iterator();
+ while (iterator.hasNext()) {
+ String quickButtonUid = iterator.next();
+ Optional quickButtonOptional = quickButtonService.findByUid(quickButtonUid);
+ if (quickButtonOptional.isPresent()) {
+ QuickButton quickButtonEntity = quickButtonOptional.get();
+
+ serviceSettings.getQuickButtons().add(quickButtonEntity);
+ }
+ }
+ }
+ robot.setServiceSettings(serviceSettings);
+ robot.setLlm(robotRequest.getLlm());
+ //
+ Robot updateRobot = save(robot);
+ if (updateRobot == null) {
+ throw new RuntimeException("update robot failed");
+ }
+
+ // TODO: 更新当前进行中会话的agent字段?
+
+ return convertToResponse(updateRobot);
+ }
+
+ @Cacheable(value = "robot", key = "#uid", unless = "#result == null")
+ @Override
+ public Optional findByUid(String uid) {
+ return robotRepository.findByUid(uid);
+ }
+
+ @Override
+ public Robot save(Robot entity) {
+ try {
+ return robotRepository.save(entity);
+ } catch (ObjectOptimisticLockingFailureException e) {
+ handleOptimisticLockingFailureException(e, entity);
+ }
+ return null;
+ }
+
+ @Override
+ public void deleteByUid(String uid) {
+ Optional robotOptional = findByUid(uid);
+ robotOptional.ifPresent(robot -> {
+ robot.setDeleted(true);
+ save(robot);
+ });
+ }
+
+ @Override
+ public void delete(Robot entity) {
+ deleteByUid(entity.getUid());
+ }
+
+ @Override
+ public void handleOptimisticLockingFailureException(ObjectOptimisticLockingFailureException e, Robot entity) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'handleOptimisticLockingFailureException'");
+ }
+
+ @Override
+ public RobotResponse convertToResponse(Robot entity) {
+ return modelMapper.map(entity, RobotResponse.class);
+ }
+
+ private Boolean existsByNicknameAndOrgUidAndDeleted(String name, String orgUid) {
+ return robotRepository.existsByNicknameAndOrgUidAndDeleted(name, orgUid, false);
+ }
+
+ public void initData() {
+
if (robotRepository.count() > 0) {
return;
}
- //
- Optional adminOptional = userService.getAdmin();
- if (adminOptional.isPresent()) {
- //
- String rid = uidUtils.getCacheSerialUid();
- Robot robot = Robot.builder()
- // .rid(rid)
- .name("客服机器人")
- .avatar(AvatarConsts.DEFAULT_AVATAR_URL)
- .description("客服机器人")
- .welcome("欢迎使用客服机器人")
- .published(false)
- .type("service")
- .llm(llmService.getLlm("user"))
- .kb(kbService.getKb(rid))
- .user(adminOptional.get())
- .build();
- robot.setUid(rid);
- robotRepository.save(robot);
- }
-
-
-
+ Kb kb = kbService.getKb(I18Consts.I18N_ROBOT_NICKNAME, UserConsts.DEFAULT_ORGANIZATION_UID);
+ RobotLlm llm = RobotLlm.builder().build();
+
+ Robot robot = Robot.builder()
+ // .nickname(I18Consts.I18N_ROBOT_NICKNAME)
+ .description(I18Consts.I18N_ROBOT_DESCRIPTION)
+ .type(RobotTypeEnum.SERVICE)
+ .orgUid(UserConsts.DEFAULT_ORGANIZATION_UID)
+ .kb(kb)
+ .llm(llm)
+ .build();
+ robot.setUid(UserConsts.DEFAULT_ROBOT_UID);
+ robot.setNickname(I18Consts.I18N_ROBOT_NICKNAME);
+ robot.setAvatar(AvatarConsts.DEFAULT_AVATAR_URL);
+ //
+ save(robot);
+
}
-
+
}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotServiceSettings.java b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotServiceSettings.java
new file mode 100644
index 0000000000..6370e4e431
--- /dev/null
+++ b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotServiceSettings.java
@@ -0,0 +1,91 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-06-04 17:16:54
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-12 10:40:16
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.ai.robot;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import com.bytedesk.core.constant.I18Consts;
+import com.bytedesk.core.quick_button.QuickButton;
+import com.bytedesk.core.thread.ThreadTypeEnum;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.OneToMany;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+@Data
+@Builder
+@Embeddable
+@Accessors(chain = true)
+@AllArgsConstructor
+@NoArgsConstructor
+public class RobotServiceSettings {
+
+ @Builder.Default
+ private String language = I18Consts.ZH_CN;
+
+ @Builder.Default
+ @Column(name = "is_auto_pop")
+ private boolean autoPop = false;
+
+ /**
+ * TODO: set different tips for different lang
+ */
+ @Builder.Default
+ private boolean showTopTip = false;
+
+ @Builder.Default
+ @Column(length = 512)
+ private String topTip = I18Consts.I18N_TOP_TIP;
+
+ @Builder.Default
+ private String welcomeTip = I18Consts.I18N_WELCOME_TIP;
+
+ @Builder.Default
+ private String leavemsgTip = I18Consts.I18N_LEAVEMSG_TIP;
+
+ /** auto close time in min - 默认自动关闭时间,单位分钟 */
+ @Builder.Default
+ private Double autoCloseMin = Double.valueOf(25);
+
+ @Builder.Default
+ @OneToMany(fetch = FetchType.LAZY)
+ private List quickButtons = new ArrayList<>();
+
+ // 是否允许转人工
+ @Builder.Default
+ private boolean allowTransferToAgent = true;
+
+ // 限制仅允许:workgroup、appointed
+ @Builder.Default
+ private ThreadTypeEnum transferType = ThreadTypeEnum.WORKGROUP;
+
+ // agentUid or workgroupUid
+ private String transferToUid;
+
+ //
+ @Builder.Default
+ private boolean showLogo = true;
+
+ // 有效日期
+ private Date validateUntil;
+}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotServiceSettingsRequest.java b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotServiceSettingsRequest.java
new file mode 100644
index 0000000000..d9b983a72f
--- /dev/null
+++ b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotServiceSettingsRequest.java
@@ -0,0 +1,91 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-06-04 17:16:54
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-11 12:29:46
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.ai.robot;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import com.bytedesk.core.constant.I18Consts;
+import com.bytedesk.core.thread.ThreadTypeEnum;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.OneToMany;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+@Data
+@Builder
+@Embeddable
+@Accessors(chain = true)
+@AllArgsConstructor
+@NoArgsConstructor
+public class RobotServiceSettingsRequest {
+
+ @Builder.Default
+ private String language = I18Consts.ZH_CN;
+
+ @Builder.Default
+ @Column(name = "is_auto_pop")
+ private boolean autoPop = false;
+
+ /**
+ * TODO: set different tips for different lang
+ */
+ @Builder.Default
+ private boolean showTopTip = false;
+
+ @Builder.Default
+ @Column(length = 512)
+ private String topTip = I18Consts.I18N_TOP_TIP;
+
+ @Builder.Default
+ private String welcomeTip = I18Consts.I18N_WELCOME_TIP;
+
+ @Builder.Default
+ private String leavemsgTip = I18Consts.I18N_LEAVEMSG_TIP;
+
+ /** auto close time in min - 默认自动关闭时间,单位分钟 */
+ @Builder.Default
+ private Double autoCloseMin = Double.valueOf(25);
+
+ @Builder.Default
+ @OneToMany(fetch = FetchType.LAZY)
+ private List quickButtonUids = new ArrayList<>();
+
+ // 是否允许转人工
+ @Builder.Default
+ private boolean allowTransferToAgent = true;
+
+ // 限制仅允许:workgroup、appointed
+ @Builder.Default
+ private ThreadTypeEnum transferType = ThreadTypeEnum.WORKGROUP;
+
+ // agentUid or workgroupUid
+ private String transferToUid;
+
+ //
+ @Builder.Default
+ private boolean showLogo = true;
+ // private String logoUrl;
+
+ // 有效日期
+ private Date validateUntil;
+}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotServiceSettingsResponse.java b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotServiceSettingsResponse.java
new file mode 100644
index 0000000000..9162865a05
--- /dev/null
+++ b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotServiceSettingsResponse.java
@@ -0,0 +1,92 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-06-04 17:16:54
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-12 10:40:36
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.ai.robot;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import com.bytedesk.core.constant.I18Consts;
+import com.bytedesk.core.quick_button.QuickButton;
+import com.bytedesk.core.thread.ThreadTypeEnum;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.OneToMany;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+@Data
+@Builder
+@Embeddable
+@Accessors(chain = true)
+@AllArgsConstructor
+@NoArgsConstructor
+public class RobotServiceSettingsResponse {
+
+ @Builder.Default
+ private String language = I18Consts.ZH_CN;
+
+ @Builder.Default
+ @Column(name = "is_auto_pop")
+ private boolean autoPop = false;
+
+ /**
+ * TODO: set different tips for different lang
+ */
+ @Builder.Default
+ private boolean showTopTip = false;
+
+ @Builder.Default
+ @Column(length = 512)
+ private String topTip = I18Consts.I18N_TOP_TIP;
+
+ @Builder.Default
+ private String welcomeTip = I18Consts.I18N_WELCOME_TIP;
+
+ @Builder.Default
+ private String leavemsgTip = I18Consts.I18N_LEAVEMSG_TIP;
+
+ /** auto close time in min - 默认自动关闭时间,单位分钟 */
+ @Builder.Default
+ private Double autoCloseMin = Double.valueOf(25);
+
+ @Builder.Default
+ @OneToMany(fetch = FetchType.LAZY)
+ private List quickButtons = new ArrayList<>();
+
+ // 是否允许转人工
+ @Builder.Default
+ private boolean allowTransferToAgent = true;
+
+ // 限制仅允许:workgroup、appointed
+ @Builder.Default
+ private ThreadTypeEnum transferType = ThreadTypeEnum.WORKGROUP;
+
+ // agentUid or workgroupUid
+ private String transferToUid;
+
+ //
+ @Builder.Default
+ private boolean showLogo = true;
+ // private String logoUrl;
+
+ // 有效日期
+ private Date validateUntil;
+}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotSpecification.java b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotSpecification.java
new file mode 100644
index 0000000000..fc5efb7612
--- /dev/null
+++ b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotSpecification.java
@@ -0,0 +1,39 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-06-12 09:07:53
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-12 09:08:56
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.ai.robot;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.data.jpa.domain.Specification;
+
+import com.bytedesk.core.base.BaseSpecification;
+
+import jakarta.persistence.criteria.Predicate;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class RobotSpecification extends BaseSpecification {
+
+ public static Specification search(RobotRequest request) {
+ log.info("request: {}", request);
+ return (root, query, criteriaBuilder) -> {
+ List predicates = new ArrayList<>();
+ predicates.addAll(getBasicPredicates(root, criteriaBuilder, request.getOrgUid()));
+ //
+ return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
+ };
+ }
+}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotTypeEnum.java b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotTypeEnum.java
new file mode 100644
index 0000000000..844acadbdf
--- /dev/null
+++ b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotTypeEnum.java
@@ -0,0 +1,40 @@
+package com.bytedesk.ai.robot;
+
+public enum RobotTypeEnum {
+ SERVICE(0), // 客服机器人
+ MARKETING(1); // 营销机器人
+
+ //
+ private final int value;
+
+ // 枚举构造器,每个枚举常量都有一个与之关联的整型值
+ RobotTypeEnum(int value) {
+ this.value = value;
+ }
+
+ // 获取枚举常量的整型值
+ public int getValue() {
+ return value;
+ }
+
+ // 根据整型值查找对应的枚举常量
+ public static RobotTypeEnum fromValue(int value) {
+ for (RobotTypeEnum type : RobotTypeEnum.values()) {
+ if (type.getValue() == value) {
+ return type;
+ }
+ }
+ throw new IllegalArgumentException("No enum constant with value " + value);
+ }
+
+ public static RobotTypeEnum fromString(String typeStr) {
+ // 使用try-catch处理可能的异常
+ try {
+ return RobotTypeEnum.valueOf(typeStr);
+ } catch (IllegalArgumentException e) {
+ // 处理错误,例如记录日志或抛出更具体的异常
+ throw new IllegalArgumentException("Invalid robot type: " + typeStr, e);
+ }
+ }
+
+}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/utils/ConvertAiUtils.java b/modules/ai/src/main/java/com/bytedesk/ai/utils/ConvertAiUtils.java
new file mode 100644
index 0000000000..7da325cb1c
--- /dev/null
+++ b/modules/ai/src/main/java/com/bytedesk/ai/utils/ConvertAiUtils.java
@@ -0,0 +1,36 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-06-06 11:28:01
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-06 11:29:36
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.ai.utils;
+
+import org.modelmapper.ModelMapper;
+
+import com.bytedesk.ai.robot.Robot;
+import com.bytedesk.ai.robot.RobotResponse;
+import com.bytedesk.ai.robot.RobotResponseSimple;
+
+public class ConvertAiUtils {
+ private ConvertAiUtils() {
+
+ }
+
+ public static RobotResponse convertToRobotResponse(Robot entity) {
+ return new ModelMapper().map(entity, RobotResponse.class);
+ }
+
+ public static RobotResponseSimple convertToRobotResponseSimple(Robot entity) {
+ return new ModelMapper().map(entity, RobotResponseSimple.class);
+ }
+
+}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/zhipuai/ZhipuAiConfig.java b/modules/ai/src/main/java/com/bytedesk/ai/zhipuai/ZhipuAiConfig.java
new file mode 100644
index 0000000000..322c6a7e74
--- /dev/null
+++ b/modules/ai/src/main/java/com/bytedesk/ai/zhipuai/ZhipuAiConfig.java
@@ -0,0 +1,83 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-05-31 10:53:11
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-05-31 11:17:06
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.ai.zhipuai;
+
+import org.springframework.ai.zhipuai.ZhiPuAiChatModel;
+import org.springframework.ai.zhipuai.ZhiPuAiChatOptions;
+import org.springframework.ai.zhipuai.ZhiPuAiEmbeddingModel;
+import org.springframework.ai.zhipuai.ZhiPuAiEmbeddingOptions;
+import org.springframework.ai.zhipuai.ZhiPuAiImageModel;
+import org.springframework.ai.zhipuai.api.ZhiPuAiApi;
+import org.springframework.ai.zhipuai.api.ZhiPuAiImageApi;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import com.zhipu.oapi.ClientV4;
+
+/**
+ * https://docs.spring.io/spring-ai/reference/api/embeddings/zhipuai-embeddings.html
+ */
+@Configuration
+public class ZhipuAiConfig {
+
+ @Value("${spring.ai.zhipu.api-key}")
+ String zhiPuAiApiKey;
+
+ @Bean
+ ZhiPuAiApi zhipuaiApi() {
+ // return new ZhiPuAiApi(System.getenv("ZHIPU_AI_API_KEY"));
+ return new ZhiPuAiApi(zhiPuAiApiKey);
+ }
+
+ @Bean
+ ZhiPuAiEmbeddingModel zhipuaiEmbeddingModel() {
+ return new ZhiPuAiEmbeddingModel(zhipuaiApi());
+ }
+
+ // https://open.bigmodel.cn/overview
+ @Bean
+ ZhiPuAiEmbeddingOptions ZhiPuAiEmbeddingOptions() {
+ return ZhiPuAiEmbeddingOptions.builder()
+ .withModel(ZhiPuAiApi.ChatModel.GLM_3_Turbo.getValue())
+ // .withModel("GLM-4")
+ .build();
+ }
+
+ @Bean
+ ZhiPuAiChatModel zhipuaiChatModel() {
+ return new ZhiPuAiChatModel(zhipuaiApi(), ZhiPuAiChatOptions.builder()
+ .withModel(ZhiPuAiApi.ChatModel.GLM_3_Turbo.getValue())
+ .withTemperature(0.4f)
+ .withMaxTokens(200)
+ .build());
+ }
+
+ @Bean
+ ZhiPuAiImageApi zhipuaiImageApi() {
+ return new ZhiPuAiImageApi(zhiPuAiApiKey);
+ }
+
+ @Bean
+ ZhiPuAiImageModel zhiPuAiImageModel() {
+ return new ZhiPuAiImageModel(zhipuaiImageApi());
+ }
+
+ @Bean
+ ClientV4 client() {
+ return new ClientV4.Builder(zhiPuAiApiKey).build();
+ }
+
+}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/zhipuai/ZhipuAiController.java b/modules/ai/src/main/java/com/bytedesk/ai/zhipuai/ZhipuAiController.java
new file mode 100644
index 0000000000..363c97a395
--- /dev/null
+++ b/modules/ai/src/main/java/com/bytedesk/ai/zhipuai/ZhipuAiController.java
@@ -0,0 +1,138 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-05-31 11:00:20
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-06 10:48:32
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.ai.zhipuai;
+
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.springframework.ai.chat.messages.UserMessage;
+import org.springframework.ai.chat.model.ChatResponse;
+import org.springframework.ai.chat.prompt.Prompt;
+import org.springframework.ai.image.ImagePrompt;
+import org.springframework.ai.image.ImageResponse;
+import org.springframework.ai.zhipuai.ZhiPuAiChatModel;
+import org.springframework.ai.zhipuai.ZhiPuAiChatOptions;
+import org.springframework.ai.zhipuai.ZhiPuAiImageModel;
+import org.springframework.ai.zhipuai.api.ZhiPuAiApi;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+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 org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
+
+import com.bytedesk.core.utils.JsonResult;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import reactor.core.publisher.Flux;
+
+/**
+ * https://open.bigmodel.cn/dev/api#sdk_install
+ * https://github.com/MetaGLM/zhipuai-sdk-java-v4
+ *
+ * https://docs.spring.io/spring-ai/reference/api/chat/zhipuai-chat.html
+ */
+@Slf4j
+@RestController
+@RequestMapping("/visitor/api/v1/zhipuai")
+@AllArgsConstructor
+public class ZhipuAiController {
+
+ private final ZhiPuAiChatModel chatModel;
+
+ private final ZhiPuAiImageModel zhiPuAiImageModel;
+
+ private final ZhipuAiService zhipuAiService;
+
+ // http://localhost:9003/visitor/api/v1/zhipuai/chat
+ @GetMapping("/chat")
+ public ResponseEntity> generation() {
+ ChatResponse response = chatModel.call(
+ new Prompt(
+ "Generate the names of 5 famous pirates.",
+ ZhiPuAiChatOptions.builder()
+ .withModel(ZhiPuAiApi.ChatModel.GLM_3_Turbo.getValue())
+ .withTemperature(0.5f)
+ .build()));
+ return ResponseEntity.ok(JsonResult.success(response));
+ }
+
+ // http://localhost:9003/visitor/api/v1/zhipuai/generate?content=hello
+ @GetMapping("/generate")
+ public Map, ?> generate(@RequestParam(value = "content", defaultValue = "讲个笑话") String content) {
+ return Map.of("generation", chatModel.call(content));
+ }
+
+ // http://localhost:9003/visitor/api/v1/zhipuai/generateStream?content=讲个笑话
+ @GetMapping("/generateStream")
+ public Flux generateStream(
+ @RequestParam(value = "content", defaultValue = "讲个笑话") String content) {
+ var prompt = new Prompt(new UserMessage(content));
+ return chatModel.stream(prompt);
+ }
+
+ // http://localhost:9003/visitor/api/v1/zhipuai/image
+ @GetMapping("/image")
+ public ResponseEntity> image() {
+ ImageResponse response = zhiPuAiImageModel.call(new ImagePrompt("A light cream colored mini golden doodle"));
+ return ResponseEntity.ok(JsonResult.success(response));
+ }
+
+ //
+
+ private final ExecutorService executorService = Executors.newSingleThreadExecutor();
+
+ // http://localhost:9003/visitor/api/v1/zhipuai/sse?uid=&sid=&content=hi
+ @GetMapping(value = "/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
+ public ResponseEntity sseEndpoint(
+ @RequestParam(value = "uid", required = true) String uid,
+ @RequestParam(value = "sid", required = true) String sid,
+ @RequestParam(value = "q", defaultValue = "讲个笑话") String question) {
+ // TODO: 根据uid和ip判断此visitor是否骚扰用户,如果骚扰则拒绝响应
+
+ log.info("sseEndpoint sid: {}, uid: {}, question {}", sid, uid, question);
+
+ SseEmitter emitter = new SseEmitter(Long.MAX_VALUE);
+
+ executorService.submit(() -> {
+ try {
+ // 调用你的服务方法来获取SSE数据
+ zhipuAiService.getSseAnswer(uid, sid, question, emitter);
+ //
+ // 将数据作为SSE事件发送
+ // emitter.send(SseEmitter.event().data(sseData));
+ // 完成后完成SSE流
+ // emitter.complete();
+ } catch (Exception e) {
+ // 如果发生错误,则发送错误事件
+ // emitter.send(SseEmitter.event().error(e));
+ emitter.completeWithError(e);
+ } finally {
+ // 确保清理资源
+ emitter.complete();
+ }
+ });
+
+ return ResponseEntity.ok().body(emitter);
+ }
+
+ // 销毁时关闭ExecutorService
+ public void destroy() {
+ executorService.shutdown();
+ }
+
+}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/zhipuai/ZhipuAiService.java b/modules/ai/src/main/java/com/bytedesk/ai/zhipuai/ZhipuAiService.java
new file mode 100644
index 0000000000..3e8449684f
--- /dev/null
+++ b/modules/ai/src/main/java/com/bytedesk/ai/zhipuai/ZhipuAiService.java
@@ -0,0 +1,210 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-06-05 15:39:22
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-11 11:43:13
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.ai.zhipuai;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.modelmapper.ModelMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
+
+import com.alibaba.fastjson2.JSON;
+import com.bytedesk.ai.robot.RobotMessage;
+import com.bytedesk.ai.robot.RobotResponseSimple;
+// import com.bytedesk.ai.robot.RobotResponseSimple;
+import com.bytedesk.core.enums.ClientEnum;
+import com.bytedesk.core.thread.Thread;
+import com.bytedesk.core.message.Message;
+import com.bytedesk.core.message.MessageService;
+import com.bytedesk.core.message.MessageStatusEnum;
+import com.bytedesk.core.message.MessageTypeEnum;
+import com.bytedesk.core.rbac.user.UserResponseSimple;
+import com.bytedesk.core.thread.ThreadService;
+import com.bytedesk.core.uid.UidUtils;
+import com.bytedesk.core.utils.JsonResult;
+import com.bytedesk.core.utils.JsonResultCodeEnum;
+import com.zhipu.oapi.ClientV4;
+// import com.zhipu.oapi.Constants;
+import com.zhipu.oapi.service.v4.model.ChatCompletionRequest;
+import com.zhipu.oapi.service.v4.model.ChatMessage;
+import com.zhipu.oapi.service.v4.model.ChatMessageAccumulator;
+import com.zhipu.oapi.service.v4.model.ChatMessageRole;
+import com.zhipu.oapi.service.v4.model.Choice;
+import com.zhipu.oapi.service.v4.model.ModelApiResponse;
+import com.zhipu.oapi.service.v4.model.ModelData;
+
+import io.reactivex.Flowable;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * https://open.bigmodel.cn/dev/api#sdk_install
+ * https://github.com/MetaGLM/zhipuai-sdk-java-v4
+ *
+ * https://docs.spring.io/spring-ai/reference/api/chat/zhipuai-chat.html
+ */
+@Slf4j
+@Service
+@AllArgsConstructor
+public class ZhipuAiService {
+
+ private final ClientV4 client;
+
+ private final UidUtils uidUtils;
+
+ private final ThreadService threadService;
+
+ private final ModelMapper modelMapper;
+
+ private final MessageService messageService;
+
+ /**
+ * sse调用
+ */
+ public void getSseAnswer(String uid, String sid, String question, SseEmitter emitter) {
+ String topic = sid + "/" + uid;
+ Thread thread = threadService.findByTopic(topic).orElseThrow(() -> new RuntimeException("thread with topic: " + topic+ " not found"));
+
+ RobotMessage robotMessage = RobotMessage.builder().question(question).build();
+
+ RobotResponseSimple robotSimple = JSON.parseObject(thread.getAgent(), RobotResponseSimple.class);
+ log.info("robotSimple {}", robotSimple);
+
+ UserResponseSimple user = modelMapper.map(thread.getAgent(), UserResponseSimple.class);
+ //
+ String messageUid = uidUtils.getCacheSerialUid();
+ Message message = Message.builder()
+ .type(MessageTypeEnum.QA)
+ .status(MessageStatusEnum.SENT)
+ .client(ClientEnum.SYSTEM)
+ .orgUid(thread.getOrgUid())
+ .user(JSON.toJSONString(user))
+ .build();
+ message.setUid(messageUid);
+ //
+ message.getThreads().add(thread);
+
+ if (!robotSimple.getLlm().isEnabled()) {
+ // 机器人未开启
+ message.setContent(JsonResultCodeEnum.ROBOT_DISABLED.getName());
+ try {
+ emitter.send(SseEmitter.event()
+ .data(JsonResult.success(
+ JsonResultCodeEnum.ROBOT_DISABLED.getName(), JsonResultCodeEnum.ROBOT_DISABLED.getValue(), message)));
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ // 完成后完成SSE流
+ emitter.complete();
+ // TODO: 关键词匹配
+
+ return;
+ }
+
+ //
+ List messages = new ArrayList<>();
+ ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), question);
+ messages.add(chatMessage);
+
+ ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
+ // 模型名称
+ // .model(Constants.ModelChatGLM3TURBO)
+ .model(robotSimple.getLlm().getModel().getValue())
+ .temperature(robotSimple.getLlm().getTemperature())
+ .topP(robotSimple.getLlm().getTopP())
+ .stream(Boolean.TRUE)
+ .messages(messages)
+ .requestId(messageUid)
+ .build();
+ //
+ ModelApiResponse sseModelApiResp = client.invokeModelApi(chatCompletionRequest);
+ if (sseModelApiResp.isSuccess()) {
+ AtomicBoolean isFirst = new AtomicBoolean(true);
+ List choices = new ArrayList<>();
+ ChatMessageAccumulator chatMessageAccumulator = mapStreamToAccumulator(sseModelApiResp.getFlowable())
+ .doOnNext(accumulator -> {
+ {
+ if (isFirst.getAndSet(false)) {
+ log.info("answer start: ");
+ robotMessage.clearAnswer();
+ message.setContent(JsonResultCodeEnum.ROBOT_ANSWER_START.getName());
+ emitter.send(SseEmitter.event().data(JsonResult.success(
+ JsonResultCodeEnum.ROBOT_ANSWER_START.getName(), JsonResultCodeEnum.ROBOT_ANSWER_START.getValue(), message)));
+ }
+ if (accumulator.getDelta() != null && accumulator.getDelta().getTool_calls() != null) {
+ String jsonString = JSON.toJSONString(accumulator.getDelta().getTool_calls());
+ log.info("tool_calls: " + jsonString);
+ }
+ if (accumulator.getDelta() != null && accumulator.getDelta().getContent() != null) {
+ String answerContent = accumulator.getDelta().getContent();
+ // delta {"role":"assistant","content":"告诉我","tool_calls":[]} answerContent 告诉我
+ robotMessage.appendAnswer(answerContent);
+ message.setContent(JSON.toJSONString(robotMessage));
+ log.info("delta {} answerContent {}", accumulator.getDelta().toString(), answerContent);
+ emitter.send(SseEmitter.event().data(JsonResult.success(
+ JsonResultCodeEnum.ROBOT_ANSWER_CONTINUE.getName(), JsonResultCodeEnum.ROBOT_ANSWER_CONTINUE.getValue(), message)));
+ }
+ }
+ })
+ .doOnComplete(() -> {
+ log.info("answer end");
+ message.setContent(JsonResultCodeEnum.ROBOT_ANSWER_END.getName());
+ emitter.send(SseEmitter.event().data(JsonResult.success(
+ JsonResultCodeEnum.ROBOT_ANSWER_END.getName(), JsonResultCodeEnum.ROBOT_ANSWER_END.getValue(), message)));
+ // 完成后完成SSE流
+ emitter.complete();
+ })
+ .lastElement()
+ .blockingGet();
+
+ ModelData data = new ModelData();
+ data.setChoices(choices);
+ data.setUsage(chatMessageAccumulator.getUsage());
+ data.setId(chatMessageAccumulator.getId());
+ data.setCreated(chatMessageAccumulator.getCreated());
+ data.setRequestId(chatCompletionRequest.getRequestId());
+ sseModelApiResp.setFlowable(null);// 打印前置空
+ sseModelApiResp.setData(data);
+
+ // 存储到数据库
+ robotMessage.setPromptTokens(chatMessageAccumulator.getUsage().getPromptTokens());
+ robotMessage.setCompletionTokens(chatMessageAccumulator.getUsage().getCompletionTokens());
+ robotMessage.setTotalTokens(chatMessageAccumulator.getUsage().getTotalTokens());
+ //
+ message.setContent(JSON.toJSONString(robotMessage));
+ messageService.save(message);
+ }
+
+ String result = JSON.toJSONString(sseModelApiResp);
+ // sse output:
+ // {"code":200,"data":{"array":false,"bigDecimal":false,"bigInteger":false,"binary":false,"boolean":false,"choices":[],
+ // "containerNode":true,"created":1717580268,"double":false,"empty":false,"float":false,"floatingPointNumber":false,
+ // "id":"8718088513501356715","int":false,"integralNumber":false,"long":false,"missingNode":false,"nodeType":"OBJECT",
+ // "null":false,"number":false,"object":true,"pojo":false,"request_id":"bytedesk-1717580267785","short":false,
+ // "textual":false,"usage":{"completion_tokens":28,"prompt_tokens":6,"total_tokens":34},"valueNode":false},"success":true}
+ log.info("sse output:" + result);
+ }
+
+ public static Flowable mapStreamToAccumulator(Flowable flowable) {
+ return flowable.map(chunk -> {
+ return new ChatMessageAccumulator(chunk.getChoices().get(0).getDelta(), null, chunk.getChoices().get(0),
+ chunk.getUsage(), chunk.getCreated(), chunk.getId());
+ });
+ }
+}
diff --git a/modules/ai/src/main/resources/application.properties b/modules/ai/src/main/resources/application.properties
index 8b13789179..f93875745c 100644
--- a/modules/ai/src/main/resources/application.properties
+++ b/modules/ai/src/main/resources/application.properties
@@ -1 +1,2 @@
+spring.application.name=ai
\ No newline at end of file
diff --git a/modules/core/.DS_Store b/modules/core/.DS_Store
index 966dd10945..e07312c045 100644
Binary files a/modules/core/.DS_Store and b/modules/core/.DS_Store differ
diff --git a/modules/core/src/.DS_Store b/modules/core/src/.DS_Store
index dedd6060e3..aef6490783 100644
Binary files a/modules/core/src/.DS_Store and b/modules/core/src/.DS_Store differ
diff --git a/modules/core/src/main/.DS_Store b/modules/core/src/main/.DS_Store
index eb12771b91..a4c92212ed 100644
Binary files a/modules/core/src/main/.DS_Store and b/modules/core/src/main/.DS_Store differ
diff --git a/modules/core/src/main/java/.DS_Store b/modules/core/src/main/java/.DS_Store
index e1a8bb72e5..5283ad450e 100644
Binary files a/modules/core/src/main/java/.DS_Store and b/modules/core/src/main/java/.DS_Store differ
diff --git a/modules/core/src/main/java/com/.DS_Store b/modules/core/src/main/java/com/.DS_Store
index e4ea19bbd8..bc76b25915 100644
Binary files a/modules/core/src/main/java/com/.DS_Store and b/modules/core/src/main/java/com/.DS_Store differ
diff --git a/modules/core/src/main/java/com/bytedesk/.DS_Store b/modules/core/src/main/java/com/bytedesk/.DS_Store
index 858c1e3d63..10e8a617ed 100644
Binary files a/modules/core/src/main/java/com/bytedesk/.DS_Store and b/modules/core/src/main/java/com/bytedesk/.DS_Store differ
diff --git a/modules/core/src/main/java/com/bytedesk/core/.DS_Store b/modules/core/src/main/java/com/bytedesk/core/.DS_Store
index ad1cf053c5..e4cdb721e3 100644
Binary files a/modules/core/src/main/java/com/bytedesk/core/.DS_Store and b/modules/core/src/main/java/com/bytedesk/core/.DS_Store differ
diff --git a/modules/core/src/main/java/com/bytedesk/core/action/Action.java b/modules/core/src/main/java/com/bytedesk/core/action/Action.java
index c7f103732a..a517839e9c 100644
--- a/modules/core/src/main/java/com/bytedesk/core/action/Action.java
+++ b/modules/core/src/main/java/com/bytedesk/core/action/Action.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-25 15:31:38
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-04 11:37:26
+ * @LastEditTime: 2024-06-07 14:44:36
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -14,9 +14,19 @@
*/
package com.bytedesk.core.action;
-import com.bytedesk.core.base.BaseEntity;
+import org.hibernate.annotations.JdbcTypeCode;
+import org.hibernate.type.SqlTypes;
+import com.bytedesk.core.base.BaseEntity;
+import com.bytedesk.core.constant.BdConstants;
+import com.bytedesk.core.constant.TypeConsts;
+import com.bytedesk.core.rbac.user.User;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+import jakarta.persistence.Column;
import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
@@ -31,7 +41,7 @@ import lombok.experimental.Accessors;
@Data
@Entity
@Builder
-@EqualsAndHashCode(callSuper=false)
+@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
@@ -39,20 +49,35 @@ import lombok.experimental.Accessors;
public class Action extends BaseEntity {
private static final long serialVersionUID = 1L;
-
- // @NotBlank
- // @Column(unique = true, nullable = false)
- // private String aid;
-
+
private String title;
private String action;
private String description;
- //
- private String userUid;
+ private String ip;
+
+ // according to ip address
+ private String ipLocation;
+
+ @Builder.Default
+ @Column(name = TypeConsts.COLUMN_NAME_TYPE)
+ private String type = TypeConsts.ACTION_TYPE_LOG;
+
+ // action failed object
+ @Builder.Default
+ @Column(columnDefinition = TypeConsts.COLUMN_TYPE_JSON)
+ @JdbcTypeCode(SqlTypes.JSON)
+ private String extra = BdConstants.EMPTY_JSON_STRING;
+
+ // private String userUid;
+ @JsonIgnore
+ @ManyToOne(fetch = FetchType.LAZY)
+ private User user;
private String orgUid;
+ @Builder.Default
+ private String platform = BdConstants.PLATFORM_BYTEDESK;
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/action/ActionLogAnnotation.java b/modules/core/src/main/java/com/bytedesk/core/action/ActionAnnotation.java
similarity index 84%
rename from modules/core/src/main/java/com/bytedesk/core/action/ActionLogAnnotation.java
rename to modules/core/src/main/java/com/bytedesk/core/action/ActionAnnotation.java
index 3030579c9b..cfb04e3e8a 100644
--- a/modules/core/src/main/java/com/bytedesk/core/action/ActionLogAnnotation.java
+++ b/modules/core/src/main/java/com/bytedesk/core/action/ActionAnnotation.java
@@ -20,8 +20,10 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import com.bytedesk.core.constant.TypeConsts;
+
/**
- * 自定义操作日志记录注解
+ * record for action and failed operations
*
* @author jackning
*
@@ -29,11 +31,13 @@ import java.lang.annotation.Target;
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
-public @interface ActionLogAnnotation {
+public @interface ActionAnnotation {
public String title() default "";
public String action() default "";
public String description() default "";
+
+ public String type() default TypeConsts.ACTION_TYPE_LOG;
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/action/ActionAspect.java b/modules/core/src/main/java/com/bytedesk/core/action/ActionAspect.java
new file mode 100644
index 0000000000..0df94dd28b
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/action/ActionAspect.java
@@ -0,0 +1,123 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-04-17 16:53:12
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-05-30 14:03:30
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.action;
+
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.AfterReturning;
+import org.aspectj.lang.annotation.AfterThrowing;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import com.bytedesk.core.ip.IpService;
+
+import jakarta.servlet.http.HttpServletRequest;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 操作日志记录处理
+ *
+ * 注意:不能在类上注解@Async,否则会获取不到 HttpServletRequest,attributes为空。
+ * 如果不需要HttpServletRequest,可以添加@Async注解
+ *
+ * @author jackning
+ */
+@Slf4j
+// @Async
+@Aspect
+@Component
+@AllArgsConstructor
+public class ActionAspect {
+
+ private final ActionService actionService;
+
+ private final IpService ipService;
+
+ /**
+ * 处理请求前执行
+ */
+ @Before(value = "@annotation(actionAnnotation)")
+ public void doBefore(JoinPoint joinPoint, ActionAnnotation actionAnnotation) {
+ log.debug("actionLog before: model {}, action {}", actionAnnotation.title(), actionAnnotation.action());
+ }
+
+ /**
+ * 处理完请求后执行
+ *
+ * @param joinPoint 切点
+ */
+ @AfterReturning(pointcut = "@annotation(actionAnnotation)", returning = "jsonResult")
+ public void doAfterReturning(JoinPoint joinPoint, ActionAnnotation actionAnnotation, Object jsonResult) {
+ log.debug("actionLog after returning: title {}, action {}", actionAnnotation.title(), actionAnnotation.action());
+ //
+ ActionRequest actionRequest = ActionRequest.builder()
+ .title(actionAnnotation.title())
+ .action(actionAnnotation.action())
+ .description(actionAnnotation.description())
+ .build();
+ actionRequest.setType(actionAnnotation.type());
+ //
+ // 获取方法签名
+ MethodSignature signature = (MethodSignature) joinPoint.getSignature();
+ // 获取方法参数列表
+ Object[] args = joinPoint.getArgs();
+ // 遍历参数
+ for (int i = 0; i < args.length; i++) {
+ // 获取参数名
+ String paramName = signature.getParameterNames()[i];
+ // 获取参数值
+ Object paramValue = args[i];
+ // 参数名: authRequest, 参数值: AuthRequest(username=admin@email.com, password=admin,
+ // mobile=null, email=null, code=null, platform=bytedesk)
+ log.debug("TODO: 参数名: {}, 参数值: {}", paramName, paramValue);
+ }
+ //
+ ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+ if (attributes != null) {
+ // 注意:不能在类上注解@Async,否则会获取不到 HttpServletRequest,attributes为空
+ HttpServletRequest request = attributes.getRequest();
+ String ipAddress = request.getRemoteAddr();
+ String ip = ipService.getIp(request);
+ String ipLocation = ipService.getIpLocation(ip);
+ log.info("ipAddress {}, ip {}, ipLocation {}", ipAddress, ip, ipLocation);
+ actionRequest.setIp(ip);
+ actionRequest.setIpLocation(ipLocation);
+ // 接下来的操作...
+ } else {
+ // 处理非Web请求情况,比如记录日志或者直接返回
+ }
+ //
+ actionService.create(actionRequest);
+ }
+
+ /**
+ * 拦截异常操作
+ *
+ * @param joinPoint 切点
+ * @param e 异常
+ */
+ @AfterThrowing(value = "@annotation(actionAnnotation)", throwing = "e")
+ public void doAfterThrowing(JoinPoint joinPoint, ActionAnnotation actionAnnotation, Exception e) {
+ log.info("actionLog after throwing: model {}, action {}", actionAnnotation.title(), actionAnnotation.action());
+ // handleLog(joinPoint, actionAnnotation, e, null);
+ }
+
+
+
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/action/ActionController.java b/modules/core/src/main/java/com/bytedesk/core/action/ActionController.java
index ff0865addd..7c5c69d5c3 100644
--- a/modules/core/src/main/java/com/bytedesk/core/action/ActionController.java
+++ b/modules/core/src/main/java/com/bytedesk/core/action/ActionController.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-25 15:40:19
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-04-25 15:40:21
+ * @LastEditTime: 2024-05-31 07:39:58
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -14,6 +14,56 @@
*/
package com.bytedesk.core.action;
-public class ActionController {
+import org.springframework.data.domain.Page;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.bytedesk.core.base.BaseController;
+import com.bytedesk.core.utils.JsonResult;
+
+import lombok.AllArgsConstructor;
+
+@RestController
+@AllArgsConstructor
+@RequestMapping("/api/v1/action")
+public class ActionController extends BaseController {
+
+ private final ActionService actionService;
+
+ @GetMapping("/query/org")
+ @Override
+ public ResponseEntity> queryByOrg(ActionRequest request) {
+
+ Page page = actionService.queryByOrg(request);
+
+ return ResponseEntity.ok(JsonResult.success(page));
+ }
+
+ @Override
+ public ResponseEntity> query(ActionRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'query'");
+ }
+
+ @Override
+ public ResponseEntity> create(ActionRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'create'");
+ }
+
+ @Override
+ public ResponseEntity> update(ActionRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'update'");
+ }
+
+ @Override
+ public ResponseEntity> delete(ActionRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'delete'");
+ }
+
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/action/ActionEvent.java b/modules/core/src/main/java/com/bytedesk/core/action/ActionEvent.java
new file mode 100644
index 0000000000..05a7218f39
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/action/ActionEvent.java
@@ -0,0 +1,35 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-05-23 09:53:53
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-05-23 10:03:03
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.action;
+
+import org.springframework.context.ApplicationEvent;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class ActionEvent extends ApplicationEvent {
+
+ private static final long serialVersionUID = 1L;
+
+ private final ActionRequest actionRequest;
+
+ public ActionEvent(Object source, ActionRequest actionRequest) {
+ super(source);
+ this.actionRequest = actionRequest;
+ }
+
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/action/ActionListener.java b/modules/core/src/main/java/com/bytedesk/core/action/ActionListener.java
new file mode 100644
index 0000000000..b9e92186c6
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/action/ActionListener.java
@@ -0,0 +1,37 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-05-23 10:00:44
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-05-23 10:04:09
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.action;
+
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@Component
+@AllArgsConstructor
+public class ActionListener {
+
+ private final ActionService actionService;
+
+ @EventListener
+ public void onActionEvent(ActionEvent event) {
+ log.info("Received event: {}", event.getActionRequest().getTitle());
+ // do something
+ actionService.create(event.getActionRequest());
+ }
+
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/action/ActionLogAspect.java b/modules/core/src/main/java/com/bytedesk/core/action/ActionLogAspect.java
deleted file mode 100644
index 339be7ed88..0000000000
--- a/modules/core/src/main/java/com/bytedesk/core/action/ActionLogAspect.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * @Author: jackning 270580156@qq.com
- * @Date: 2024-04-17 16:53:12
- * @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-04 12:33:32
- * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
- * Please be aware of the BSL license restrictions before installing Bytedesk IM –
- * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
- * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
- * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
- * contact: 270580156@qq.com
- * 联系:270580156@qq.com
- * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
- */
-package com.bytedesk.core.action;
-
-import org.aspectj.lang.JoinPoint;
-import org.aspectj.lang.annotation.AfterReturning;
-import org.aspectj.lang.annotation.AfterThrowing;
-import org.aspectj.lang.annotation.Aspect;
-import org.aspectj.lang.annotation.Before;
-import org.springframework.scheduling.annotation.Async;
-import org.springframework.stereotype.Component;
-
-import lombok.AllArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-
-/**
- * 操作日志记录处理
- *
- * @author jackning
- */
-@Slf4j
-@Async
-@Aspect
-@Component
-@AllArgsConstructor
-public class ActionLogAspect {
-
- private final ActionService actionService;
-
- /**
- * 处理请求前执行
- */
- @Before(value = "@annotation(controllerLog)")
- public void doBefore(JoinPoint joinPoint, ActionLogAnnotation controllerLog) {
- log.debug("actionLog before: model {}, action {}", controllerLog.title(), controllerLog.action());
- }
-
- /**
- * 处理完请求后执行
- *
- * @param joinPoint 切点
- */
- @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")
- public void doAfterReturning(JoinPoint joinPoint, ActionLogAnnotation controllerLog, Object jsonResult) {
- log.debug("actionLog after returning: model {}, action {}, jsonResult {}", controllerLog.title(),
- controllerLog.action(), jsonResult);
- // handleLog(joinPoint, controllerLog, null, jsonResult);
- // TODO: 记录具体用户
- ActionRequest actionRequest = ActionRequest.builder()
- .title(controllerLog.title())
- .action(controllerLog.action())
- .description(controllerLog.description())
- .build();
- actionService.create(actionRequest);
- }
-
- /**
- * 拦截异常操作
- *
- * @param joinPoint 切点
- * @param e 异常
- */
- @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")
- public void doAfterThrowing(JoinPoint joinPoint, ActionLogAnnotation controllerLog, Exception e) {
- log.info("actionLog after throwing: model {}, action {}", controllerLog.title(), controllerLog.action());
- // handleLog(joinPoint, controllerLog, e, null);
- }
-
-
- // protected void handleLog(final JoinPoint joinPoint, ActionLog controllerLog, final Exception e, Object jsonResult) {
- // log.debug("actionLog handleLog: model {}, action {}", controllerLog.title(), controllerLog.action());
- // // TODO: write to db
- // }
-
-
-}
diff --git a/modules/core/src/main/java/com/bytedesk/core/action/ActionRepository.java b/modules/core/src/main/java/com/bytedesk/core/action/ActionRepository.java
index ebe1a9db34..be98ef1e1f 100644
--- a/modules/core/src/main/java/com/bytedesk/core/action/ActionRepository.java
+++ b/modules/core/src/main/java/com/bytedesk/core/action/ActionRepository.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-25 15:40:53
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-04-25 15:40:55
+ * @LastEditTime: 2024-05-30 16:10:00
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -15,8 +15,8 @@
package com.bytedesk.core.action;
import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
-public interface ActionRepository extends JpaRepository {
+public interface ActionRepository extends JpaRepository, JpaSpecificationExecutor {
-
}
\ No newline at end of file
diff --git a/modules/core/src/main/java/com/bytedesk/core/action/ActionRequest.java b/modules/core/src/main/java/com/bytedesk/core/action/ActionRequest.java
index 6cad17937b..5f8129cec3 100644
--- a/modules/core/src/main/java/com/bytedesk/core/action/ActionRequest.java
+++ b/modules/core/src/main/java/com/bytedesk/core/action/ActionRequest.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-25 15:40:29
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-04 11:49:01
+ * @LastEditTime: 2024-05-23 23:37:53
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -15,6 +15,7 @@
package com.bytedesk.core.action;
import com.bytedesk.core.base.BaseRequest;
+import com.bytedesk.core.constant.BdConstants;
import lombok.AllArgsConstructor;
import lombok.Builder;
@@ -30,13 +31,24 @@ import lombok.experimental.Accessors;
public class ActionRequest extends BaseRequest {
private static final long serialVersionUID = 1L;
-
- // private String aid;
-
+
private String title;
private String action;
private String description;
+
+ private String ip;
+
+ // according to ip address
+ private String ipLocation;
+
+ private String extra;
+ private String orgUid;
+
+ private String nickname;
+
+ @Builder.Default
+ private String platform = BdConstants.PLATFORM_BYTEDESK;
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/action/ActionResponse.java b/modules/core/src/main/java/com/bytedesk/core/action/ActionResponse.java
index 6ee3110763..9f92deee9c 100644
--- a/modules/core/src/main/java/com/bytedesk/core/action/ActionResponse.java
+++ b/modules/core/src/main/java/com/bytedesk/core/action/ActionResponse.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-25 15:40:39
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-04 11:49:07
+ * @LastEditTime: 2024-05-28 11:05:24
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -14,26 +14,44 @@
*/
package com.bytedesk.core.action;
-import com.bytedesk.core.base.BaseResponse;
+import java.util.Date;
+import com.bytedesk.core.base.BaseResponse;
+import com.bytedesk.core.rbac.user.UserResponseSimple;
+
+import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Data
@Builder
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
+@AllArgsConstructor
+@NoArgsConstructor
public class ActionResponse extends BaseResponse {
private static final long serialVersionUID = 1L;
-
- // private String aid;
-
+
private String title;
private String action;
private String description;
+
+ private String ip;
+
+ // according to ip address
+ private String ipLocation;
+
+ private String type;
+
+ private String extra;
+
+ private UserResponseSimple user;
+
+ public Date createdAt;
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/action/ActionService.java b/modules/core/src/main/java/com/bytedesk/core/action/ActionService.java
index ded0de70c0..67655eeaac 100644
--- a/modules/core/src/main/java/com/bytedesk/core/action/ActionService.java
+++ b/modules/core/src/main/java/com/bytedesk/core/action/ActionService.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-25 15:41:47
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-04 11:37:38
+ * @LastEditTime: 2024-05-30 16:02:31
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -14,16 +14,28 @@
*/
package com.bytedesk.core.action;
+import java.util.Optional;
+
import org.modelmapper.ModelMapper;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort.Direction;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.orm.ObjectOptimisticLockingFailureException;
import org.springframework.stereotype.Service;
+import com.bytedesk.core.base.BaseService;
+import com.bytedesk.core.constant.UserConsts;
+import com.bytedesk.core.rbac.auth.AuthService;
+import com.bytedesk.core.rbac.user.User;
import com.bytedesk.core.uid.UidUtils;
import lombok.AllArgsConstructor;
@Service
@AllArgsConstructor
-public class ActionService {
+public class ActionService extends BaseService {
private final ActionRepository actionRepository;
@@ -31,20 +43,77 @@ public class ActionService {
private final UidUtils uidUtils;
- public Action create(ActionRequest actionRequest) {
+ private final AuthService authService;
+
+ public ActionResponse create(ActionRequest actionRequest) {
Action action = modelMapper.map(actionRequest, Action.class);
action.setUid(uidUtils.getCacheSerialUid());
-
- return save(action);
+ //
+ User user = authService.getCurrentUser();
+ if (user != null) {
+ action.setUser(user);
+ action.setOrgUid(user.getOrgUid());
+ } else {
+ action.setOrgUid(UserConsts.DEFAULT_ORGANIZATION_UID);
+ }
+ //
+ return convertToResponse(save(action));
}
public Action save(Action action) {
return actionRepository.save(action);
}
- public ActionResponse convertToActionResponse(Action action) {
+ public ActionResponse convertToResponse(Action action) {
return modelMapper.map(action, ActionResponse.class);
}
+
+ @Override
+ public Page queryByOrg(ActionRequest request) {
+
+ Pageable pageable = PageRequest.of(request.getPageNumber(), request.getPageSize(), Direction.DESC, "updatedAt");
+ //
+ Specification spec = ActionSpecs.search(request);
+ Page page = actionRepository.findAll(spec, pageable);
+
+ return page.map(action -> convertToResponse(action));
+ }
+
+ @Override
+ public Page queryByUser(ActionRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'queryByUser'");
+ }
+
+ @Override
+ public Optional findByUid(String uid) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'findByUid'");
+ }
+
+ @Override
+ public ActionResponse update(ActionRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'update'");
+ }
+
+ @Override
+ public void deleteByUid(String uid) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'deleteByUid'");
+ }
+
+ @Override
+ public void delete(Action entity) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'delete'");
+ }
+
+ @Override
+ public void handleOptimisticLockingFailureException(ObjectOptimisticLockingFailureException e, Action entity) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'handleOptimisticLockingFailureException'");
+ }
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/action/ActionSpecs.java b/modules/core/src/main/java/com/bytedesk/core/action/ActionSpecs.java
new file mode 100644
index 0000000000..577bf69bab
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/action/ActionSpecs.java
@@ -0,0 +1,60 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-05-30 15:49:34
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-05 23:10:25
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.action;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.util.StringUtils;
+
+import com.bytedesk.core.base.BaseSpecification;
+
+import jakarta.persistence.criteria.Predicate;
+
+public class ActionSpecs extends BaseSpecification {
+
+ public static Specification search(ActionRequest request) {
+ return (root, query, criteriaBuilder) -> {
+ List predicates = new ArrayList<>();
+ predicates.addAll(getBasicPredicates(root, criteriaBuilder, request.getOrgUid()));
+ //
+ if (StringUtils.hasText(request.getTitle())) {
+ predicates.add(criteriaBuilder.like(root.get("title"), "%" + request.getTitle() + "%"));
+ }
+ if (StringUtils.hasText(request.getAction())) {
+ predicates.add(criteriaBuilder.like(root.get("action"), "%" + request.getAction() + "%"));
+ }
+ if (StringUtils.hasText(request.getDescription())) {
+ predicates.add(criteriaBuilder.like(root.get("description"), "%" + request.getDescription() + "%"));
+ }
+ if (StringUtils.hasText(request.getIp())) {
+ predicates.add(criteriaBuilder.like(root.get("ip"), "%" + request.getIp() + "%"));
+ }
+ if (StringUtils.hasText(request.getIpLocation())) {
+ predicates.add(criteriaBuilder.like(root.get("ipLocation"), "%" + request.getIpLocation() + "%"));
+ }
+ if (StringUtils.hasText(request.getType())) {
+ predicates.add(criteriaBuilder.like(root.get("type"), "%" + request.getType() + "%"));
+ }
+ if (StringUtils.hasText(request.getNickname())) {
+ predicates
+ .add(criteriaBuilder.like(root.get("user").get("nickname"), "%" + request.getNickname() + "%"));
+ }
+
+ return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
+ };
+ }
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/asistant/Asistant.java b/modules/core/src/main/java/com/bytedesk/core/asistant/Asistant.java
index 5e7b2973eb..1be2f77b41 100644
--- a/modules/core/src/main/java/com/bytedesk/core/asistant/Asistant.java
+++ b/modules/core/src/main/java/com/bytedesk/core/asistant/Asistant.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-26 20:32:23
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-04 10:46:28
+ * @LastEditTime: 2024-06-07 14:52:08
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -15,6 +15,9 @@
package com.bytedesk.core.asistant;
import com.bytedesk.core.base.BaseEntity;
+import com.bytedesk.core.constant.AvatarConsts;
+import com.bytedesk.core.constant.I18Consts;
+import com.bytedesk.core.constant.TypeConsts;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
@@ -38,25 +41,24 @@ import lombok.experimental.Accessors;
@AllArgsConstructor
@NoArgsConstructor
@EntityListeners({ AsistantListener.class })
+// @DiscriminatorValue("Asistant")
@Table(name = "core_asistant")
public class Asistant extends BaseEntity {
private static final long serialVersionUID = 1L;
-
- // @NotBlank
- // @Column(unique = true, nullable = false, length = 127)
- // private String aid;
private String topic;
- @Column(name = "by_type")
+ @Column(name = TypeConsts.COLUMN_NAME_TYPE)
private String type;
-
- private String name;
-
- private String avatar;
- private String description;
+ private String nickname;
+
+ @Builder.Default
+ private String avatar = AvatarConsts.DEFAULT_AVATAR_URL;
+
+ @Builder.Default
+ private String description = I18Consts.I18N_USER_DESCRIPTION;
/** belong to org */
private String orgUid;
diff --git a/modules/core/src/main/java/com/bytedesk/core/asistant/AsistantListener.java b/modules/core/src/main/java/com/bytedesk/core/asistant/AsistantListener.java
index 4b3701b958..b35de7ce4e 100644
--- a/modules/core/src/main/java/com/bytedesk/core/asistant/AsistantListener.java
+++ b/modules/core/src/main/java/com/bytedesk/core/asistant/AsistantListener.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-27 12:09:59
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-04-27 13:00:43
+ * @LastEditTime: 2024-06-04 15:45:47
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -23,11 +23,11 @@ import lombok.extern.slf4j.Slf4j;
@Component
public class AsistantListener {
-
@PostPersist
public void onPostPersist(Asistant asistant) {
- log.debug("AsistantListener: onPostPersist {}", asistant.getName());
+ log.debug("AsistantListener: onPostPersist {}", asistant.getNickname());
+
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/asistant/AsistantRequest.java b/modules/core/src/main/java/com/bytedesk/core/asistant/AsistantRequest.java
index 87efbe3b1c..1f84f373be 100644
--- a/modules/core/src/main/java/com/bytedesk/core/asistant/AsistantRequest.java
+++ b/modules/core/src/main/java/com/bytedesk/core/asistant/AsistantRequest.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-26 21:05:09
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-04 10:45:56
+ * @LastEditTime: 2024-06-04 15:31:02
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -31,7 +31,7 @@ public class AsistantRequest extends BaseRequest {
private String topic;
- private String name;
+ private String nickname;
private String avatar;
diff --git a/modules/core/src/main/java/com/bytedesk/core/asistant/AsistantResponse.java b/modules/core/src/main/java/com/bytedesk/core/asistant/AsistantResponse.java
index 4dbd2185e7..8608be1bc3 100644
--- a/modules/core/src/main/java/com/bytedesk/core/asistant/AsistantResponse.java
+++ b/modules/core/src/main/java/com/bytedesk/core/asistant/AsistantResponse.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-26 21:05:21
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-04 10:42:21
+ * @LastEditTime: 2024-06-04 15:30:55
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -33,7 +33,7 @@ public class AsistantResponse extends BaseResponse {
private String type;
- private String name;
+ private String nickname;
private String avatar;
diff --git a/modules/core/src/main/java/com/bytedesk/core/asistant/AsistantService.java b/modules/core/src/main/java/com/bytedesk/core/asistant/AsistantService.java
index 776dd568de..27ff3db8e0 100644
--- a/modules/core/src/main/java/com/bytedesk/core/asistant/AsistantService.java
+++ b/modules/core/src/main/java/com/bytedesk/core/asistant/AsistantService.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-26 21:04:54
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-08 10:25:53
+ * @LastEditTime: 2024-06-04 15:31:23
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -81,50 +81,17 @@ public class AsistantService {
return;
}
- // Optional adminOptional = userService.getAdmin();
-
AsistantRequest asistantRequest = AsistantRequest.builder()
.topic(TopicConsts.TOPIC_FILE_ASISTANT)
- .name(I18Consts.I18N_FILE_ASISTANT_NAME)
+ .nickname(I18Consts.I18N_FILE_ASISTANT_NAME)
.avatar(AvatarConsts.DEFAULT_FILE_ASISTANT_AVATAR_URL)
.description(I18Consts.I18N_FILE_ASISTANT_DESCRIPTION)
- // .orgUid(adminOptional.get().getOrgUid())
.orgUid(UserConsts.DEFAULT_ORGANIZATION_UID)
.build();
asistantRequest.setUid(UserConsts.DEFAULT_FILE_ASISTANT_UID);
asistantRequest.setType(TypeConsts.TYPE_SYSTEM);
create(asistantRequest);
- // 方便测试,默认给每个初始用户生成一个跟 文件助手 的对话
- // UserRequest userRequest = new UserRequest();
- // userRequest.setPageNumber(0);
- // userRequest.setPageSize(10);
- // //
- // Page userPage = userService.query(userRequest);
- // userPage.forEach(user -> {
- // //
- // UserResponseSimple userSimple = UserResponseSimple.builder()
- // // .uid(asistantRequest.getAid())
- // .nickname(asistantRequest.getName())
- // .avatar(asistantRequest.getAvatar())
- // .build();
- // userSimple.setUid(asistantRequest.getUid());
- // //
- // Thread thread = Thread.builder()
- // // .tid(uidUtils.getCacheSerialUid())
- // .type(ThreadTypeConsts.ASISTANT)
- // .topic(TopicConsts.TOPIC_FILE_ASISTANT + "/" + user.getUid())
- // .status(StatusConsts.THREAD_STATUS_INIT)
- // .client(TypeConsts.TYPE_SYSTEM)
- // .user(JSON.toJSONString(userSimple))
- // .owner(user)
- // .orgUid(asistantRequest.getOrgUid())
- // .build();
- // thread.setUid(uidUtils.getCacheSerialUid());
-
- // threadService.save(thread);
- // });
-
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/base/BaseController.java b/modules/core/src/main/java/com/bytedesk/core/base/BaseController.java
index 0d4c71e004..cce0279d43 100644
--- a/modules/core/src/main/java/com/bytedesk/core/base/BaseController.java
+++ b/modules/core/src/main/java/com/bytedesk/core/base/BaseController.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-05-10 12:16:43
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-14 11:06:53
+ * @LastEditTime: 2024-05-31 07:39:48
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -29,7 +29,7 @@ public abstract class BaseController {
* @param request
* @return
*/
- @GetMapping("/org")
+ @GetMapping("/query/org")
abstract public ResponseEntity> queryByOrg(T request);
/**
@@ -67,11 +67,4 @@ public abstract class BaseController {
@PostMapping("/delete")
abstract public ResponseEntity> delete(@RequestBody T request);
- /**
- * filter
- *
- * @return json
- */
- @GetMapping("/filter")
- abstract public ResponseEntity> filter(T filterParam);
}
\ No newline at end of file
diff --git a/modules/core/src/main/java/com/bytedesk/core/base/BaseRequest.java b/modules/core/src/main/java/com/bytedesk/core/base/BaseRequest.java
index 1636e2f0e3..ccd42d4474 100644
--- a/modules/core/src/main/java/com/bytedesk/core/base/BaseRequest.java
+++ b/modules/core/src/main/java/com/bytedesk/core/base/BaseRequest.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-29 16:21:24
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-11 15:36:45
+ * @LastEditTime: 2024-05-24 21:25:26
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -23,7 +23,7 @@ import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = false)
public abstract class BaseRequest implements Serializable {
- private String uid;
+ public String uid;
public int pageNumber;
diff --git a/modules/core/src/main/java/com/bytedesk/core/base/BaseService.java b/modules/core/src/main/java/com/bytedesk/core/base/BaseService.java
index 219c191e3f..db48db76c6 100644
--- a/modules/core/src/main/java/com/bytedesk/core/base/BaseService.java
+++ b/modules/core/src/main/java/com/bytedesk/core/base/BaseService.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-05-10 12:13:37
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-15 14:19:12
+ * @LastEditTime: 2024-05-24 15:48:02
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -36,7 +36,7 @@ public abstract class BaseService {
abstract public T save(T entity);
- abstract public void deleteByUid(TRequest request);
+ abstract public void deleteByUid(String uid);
abstract public void delete(T entity);
diff --git a/modules/core/src/main/java/com/bytedesk/core/base/BaseSpecification.java b/modules/core/src/main/java/com/bytedesk/core/base/BaseSpecification.java
new file mode 100644
index 0000000000..ada9ee7580
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/base/BaseSpecification.java
@@ -0,0 +1,32 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-05-30 15:59:30
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-07 15:03:22
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.base;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import jakarta.persistence.criteria.CriteriaBuilder;
+import jakarta.persistence.criteria.Predicate;
+import jakarta.persistence.criteria.Root;
+
+public abstract class BaseSpecification {
+
+ public static List getBasicPredicates(Root> root, CriteriaBuilder criteriaBuilder, String orgUid) {
+ List predicates = new ArrayList<>();
+ predicates.add(criteriaBuilder.equal(root.get("orgUid"), orgUid));
+ predicates.add(criteriaBuilder.equal(root.get("deleted"), false));
+ return predicates;
+ }
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/base/BaseUser.java b/modules/core/src/main/java/com/bytedesk/core/base/BaseUser.java
new file mode 100644
index 0000000000..2e13467c59
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/base/BaseUser.java
@@ -0,0 +1,37 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-05-31 12:53:03
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-04 16:18:07
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.base;
+
+import com.bytedesk.core.constant.AvatarConsts;
+
+import jakarta.persistence.MappedSuperclass;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper=false)
+// @Entity
+// @Table(name = "core_base_user")
+// @Inheritance()
+// @DiscriminatorColumn(name = "user_type")
+@MappedSuperclass
+public abstract class BaseUser extends BaseEntity {
+
+ private String nickname;
+
+ private String avatar = AvatarConsts.DEFAULT_AVATAR_URL;
+
+
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/category/Category.java b/modules/core/src/main/java/com/bytedesk/core/category/Category.java
index 92be075ba2..d856bb41ea 100644
--- a/modules/core/src/main/java/com/bytedesk/core/category/Category.java
+++ b/modules/core/src/main/java/com/bytedesk/core/category/Category.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-05-03 18:13:55
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-20 10:01:28
+ * @LastEditTime: 2024-06-11 11:52:28
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -19,6 +19,7 @@ import java.util.ArrayList;
import com.bytedesk.core.base.BaseEntity;
import com.bytedesk.core.constant.BdConstants;
+import com.bytedesk.core.constant.TypeConsts;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.CascadeType;
@@ -50,9 +51,9 @@ public class Category extends BaseEntity {
// private String description;
- @Column(name = "by_type")
+ @Column(name = TypeConsts.COLUMN_NAME_TYPE)
private String type;
-
+
private String icon;
// @Column(unique = true)
@@ -62,7 +63,7 @@ public class Category extends BaseEntity {
* 排序
*/
@Builder.Default
- private Integer orderNo = 0;
+ private int orderNo = 0;
@JsonIgnore
@ManyToOne(fetch = FetchType.LAZY)
@@ -75,7 +76,7 @@ public class Category extends BaseEntity {
private List children = new ArrayList<>();
@Builder.Default
- private String platform = BdConstants.PLATFORM_BYTEDESK;
+ private String platform = BdConstants.PLATFORM_BYTEDESK;
/** belong to org */
private String orgUid;
diff --git a/modules/core/src/main/java/com/bytedesk/core/category/CategoryConsts.java b/modules/core/src/main/java/com/bytedesk/core/category/CategoryConsts.java
new file mode 100644
index 0000000000..e7405513b6
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/category/CategoryConsts.java
@@ -0,0 +1,14 @@
+package com.bytedesk.core.category;
+
+public class CategoryConsts {
+ private CategoryConsts() {
+ }
+ //
+ public static final String CATEGORY_TYPE_QUICK_REPLY = "quick_reply";
+ public static final String CATEGORY_TYPE_FAQ = "faq";
+ //
+ public static final String CATEGORY_TYPE_HELP_DOC = "help_doc";
+ public static final String CATEGORY_TYPE_ROBOT_KB = "robot_kb";
+ public static final String CATEGORY_TYPE_BLOG = "blog";
+ public static final String CATEGORY_TYPE_EMAIL = "email";
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/category/CategoryController.java b/modules/core/src/main/java/com/bytedesk/core/category/CategoryController.java
index 6a6283d940..ca0305fd08 100644
--- a/modules/core/src/main/java/com/bytedesk/core/category/CategoryController.java
+++ b/modules/core/src/main/java/com/bytedesk/core/category/CategoryController.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-05-11 18:21:26
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-20 12:51:23
+ * @LastEditTime: 2024-06-08 16:47:17
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -14,11 +14,16 @@
*/
package com.bytedesk.core.category;
+import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+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;
import com.bytedesk.core.base.BaseController;
+import com.bytedesk.core.utils.JsonResult;
import lombok.AllArgsConstructor;
@@ -27,12 +32,15 @@ import lombok.AllArgsConstructor;
@RequestMapping("/api/v1/category")
public class CategoryController extends BaseController {
- // private final CategoryService categoryService;
+ private final CategoryService categoryService;
+ @GetMapping("/query/org")
@Override
public ResponseEntity> queryByOrg(CategoryRequest request) {
- // TODO Auto-generated method stub
- throw new UnsupportedOperationException("Unimplemented method 'queryByOrg'");
+
+ Page page = categoryService.queryByOrg(request);
+
+ return ResponseEntity.ok(JsonResult.success(page));
}
@Override
@@ -41,31 +49,32 @@ public class CategoryController extends BaseController {
throw new UnsupportedOperationException("Unimplemented method 'query'");
}
+ @PostMapping("/create")
@Override
- public ResponseEntity> create(CategoryRequest request) {
- // TODO Auto-generated method stub
- throw new UnsupportedOperationException("Unimplemented method 'create'");
+ public ResponseEntity> create(@RequestBody CategoryRequest request) {
+
+ CategoryResponse response = categoryService.create(request);
+
+ return ResponseEntity.ok(JsonResult.success(response));
}
+ @PostMapping("/update")
@Override
- public ResponseEntity> update(CategoryRequest request) {
- // TODO Auto-generated method stub
- throw new UnsupportedOperationException("Unimplemented method 'update'");
+ public ResponseEntity> update(@RequestBody CategoryRequest request) {
+
+ CategoryResponse response = categoryService.update(request);
+
+ return ResponseEntity.ok(JsonResult.success(response));
}
+ @PostMapping("/delete")
@Override
- public ResponseEntity> delete(CategoryRequest request) {
- // TODO Auto-generated method stub
- throw new UnsupportedOperationException("Unimplemented method 'delete'");
+ public ResponseEntity> delete(@RequestBody CategoryRequest request) {
+
+ categoryService.deleteByUid(request.getUid());
+
+ return ResponseEntity.ok(JsonResult.success("delete success", request.getUid()));
}
- @Override
- public ResponseEntity> filter(CategoryRequest filterParam) {
- // TODO Auto-generated method stub
- throw new UnsupportedOperationException("Unimplemented method 'filter'");
- }
-
-
-
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/category/CategoryRepository.java b/modules/core/src/main/java/com/bytedesk/core/category/CategoryRepository.java
index cac41d6eac..8e751c09e6 100644
--- a/modules/core/src/main/java/com/bytedesk/core/category/CategoryRepository.java
+++ b/modules/core/src/main/java/com/bytedesk/core/category/CategoryRepository.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-05-11 18:21:36
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-20 14:01:05
+ * @LastEditTime: 2024-06-08 13:29:49
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -18,12 +18,10 @@ import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
-public interface CategoryRepository extends JpaRepository {
-
+public interface CategoryRepository extends JpaRepository, JpaSpecificationExecutor {
Optional findByUid(String uid);
-
List findByParentAndPlatformOrderByOrderNoAsc(Category parent, String platform);
-
- Boolean existsByPlatform(String platform);
+ // Boolean existsByPlatform(String platform);
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/category/CategoryRequest.java b/modules/core/src/main/java/com/bytedesk/core/category/CategoryRequest.java
index 94696b9fc6..4074dd08bf 100644
--- a/modules/core/src/main/java/com/bytedesk/core/category/CategoryRequest.java
+++ b/modules/core/src/main/java/com/bytedesk/core/category/CategoryRequest.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-05-11 18:21:44
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-18 18:11:14
+ * @LastEditTime: 2024-06-08 15:24:07
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -14,9 +14,11 @@
*/
package com.bytedesk.core.category;
-import java.util.Set;
+import java.util.List;
+import java.util.ArrayList;
import com.bytedesk.core.base.BaseRequest;
+import com.bytedesk.core.constant.BdConstants;
import lombok.AllArgsConstructor;
import lombok.Builder;
@@ -37,9 +39,15 @@ public class CategoryRequest extends BaseRequest {
private String icon;
- private Integer orderNo;
+ @Builder.Default
+ private Integer orderNo = 0;
- private String platform;
+ @Builder.Default
+ private String platform = BdConstants.PLATFORM_BYTEDESK;
- private Set children;
+ @Builder.Default
+ private List children = new ArrayList<>();
+
+ /** belong to org */
+ private String orgUid;
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/category/CategoryResponse.java b/modules/core/src/main/java/com/bytedesk/core/category/CategoryResponse.java
index f5d5b38c04..2a7a746285 100644
--- a/modules/core/src/main/java/com/bytedesk/core/category/CategoryResponse.java
+++ b/modules/core/src/main/java/com/bytedesk/core/category/CategoryResponse.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-05-11 18:21:53
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-18 18:15:43
+ * @LastEditTime: 2024-06-08 16:54:49
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -14,8 +14,6 @@
*/
package com.bytedesk.core.category;
-import java.util.List;
-
import com.bytedesk.core.base.BaseResponse;
import lombok.AllArgsConstructor;
@@ -41,7 +39,5 @@ public class CategoryResponse extends BaseResponse {
private Integer orderNo;
- // private String platform;
-
- private List children;
+ // private List children;
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/category/CategoryService.java b/modules/core/src/main/java/com/bytedesk/core/category/CategoryService.java
index d483b40873..b8c0c9172e 100644
--- a/modules/core/src/main/java/com/bytedesk/core/category/CategoryService.java
+++ b/modules/core/src/main/java/com/bytedesk/core/category/CategoryService.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-05-11 18:22:04
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-18 18:19:19
+ * @LastEditTime: 2024-06-08 16:54:59
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -21,10 +21,15 @@ import java.util.stream.Collectors;
import org.modelmapper.ModelMapper;
import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.jpa.domain.Specification;
import org.springframework.orm.ObjectOptimisticLockingFailureException;
import org.springframework.stereotype.Service;
import com.bytedesk.core.base.BaseService;
+import com.bytedesk.core.uid.UidUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -37,6 +42,8 @@ public class CategoryService extends BaseService findByNullParent(String platform) {
// 一级分类
@@ -57,8 +64,15 @@ public class CategoryService extends BaseService queryByOrg(CategoryRequest request) {
- // TODO Auto-generated method stub
- throw new UnsupportedOperationException("Unimplemented method 'queryByOrg'");
+
+ Pageable pageable = PageRequest.of(request.getPageNumber(), request.getPageSize(), Sort.Direction.ASC,
+ "updatedAt");
+
+ Specification specs = CategorySpecification.search(request);
+
+ Page page = categoryRepository.findAll(specs, pageable);
+
+ return page.map(this::convertToResponse);
}
@Override
@@ -74,25 +88,56 @@ public class CategoryService extends BaseService category = findByUid(request.getUid());
+ if (!category.isPresent()) {
+ throw new RuntimeException("category not found");
+ }
+
+ Category entity = category.get();
+ // modelMapper.map(request, entity);
+ entity.setName(request.getName());
+ entity.setIcon(request.getIcon());
+ entity.setType(request.getType());
+ // entity.setPlatform(request.getPlatform());
+
+ // TODO: children
+
+ Category newCategory = save(entity);
+ if (newCategory == null) {
+ throw new RuntimeException("category save error");
+ }
+
+ return convertToResponse(newCategory);
}
@Override
public Category save(Category entity) {
- return categoryRepository.save(entity);
+ try {
+ return categoryRepository.save(entity);
+ } catch (ObjectOptimisticLockingFailureException e) {
+ handleOptimisticLockingFailureException(e, entity);
+ }
+ return null;
}
@Override
- public void deleteByUid(CategoryRequest request) {
- // TODO Auto-generated method stub
- throw new UnsupportedOperationException("Unimplemented method 'deleteByUid'");
+ public void deleteByUid(String uid) {
+ Optional category = findByUid(uid);
+ if (category.isPresent()) {
+ category.get().setDeleted(true);
+ save(category.get());
+ }
}
@Override
@@ -113,7 +158,8 @@ public class CategoryService extends BaseService search(CategoryRequest request) {
+ log.info("request: {}", request);
+ return (root, query, criteriaBuilder) -> {
+ List predicates = new ArrayList<>();
+ predicates.addAll(getBasicPredicates(root, criteriaBuilder, request.getOrgUid()));
+ //
+ if (StringUtils.hasText(request.getName())) {
+ predicates.add(criteriaBuilder.like(root.get("name"), "%" + request.getName() + "%"));
+ }
+ if (StringUtils.hasText(request.getType())) {
+ predicates.add(criteriaBuilder.like(root.get("type"), "%" + request.getType() + "%"));
+ }
+ //
+ return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
+ };
+ }
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/channel/Channel.java b/modules/core/src/main/java/com/bytedesk/core/channel/Channel.java
index 9fa4380b64..cf9fa9ddaa 100644
--- a/modules/core/src/main/java/com/bytedesk/core/channel/Channel.java
+++ b/modules/core/src/main/java/com/bytedesk/core/channel/Channel.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-26 20:34:52
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-04 10:47:12
+ * @LastEditTime: 2024-06-07 14:52:21
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -15,6 +15,9 @@
package com.bytedesk.core.channel;
import com.bytedesk.core.base.BaseEntity;
+import com.bytedesk.core.constant.AvatarConsts;
+import com.bytedesk.core.constant.I18Consts;
+import com.bytedesk.core.constant.TypeConsts;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
@@ -37,28 +40,27 @@ import lombok.experimental.Accessors;
@EqualsAndHashCode(callSuper = true)
@AllArgsConstructor
@NoArgsConstructor
-@EntityListeners({ChannelListener.class})
+@EntityListeners({ ChannelListener.class })
+// @DiscriminatorValue("Channel")
@Table(name = "core_channel")
public class Channel extends BaseEntity {
private static final long serialVersionUID = 1L;
- // @Column(unique = true, nullable = false, length = 127)
- // private String cid;
-
private String topic;
- @Column(name = "by_type")
+ @Column(name = TypeConsts.COLUMN_NAME_TYPE)
private String type;
-
- private String name;
-
- private String avatar;
- private String description;
+ private String nickname;
+
+ @Builder.Default
+ private String avatar = AvatarConsts.DEFAULT_AVATAR_URL;
+
+ @Builder.Default
+ private String description = I18Consts.I18N_USER_DESCRIPTION;
/** belong to org */
private String orgUid;
-
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/channel/ChannelListener.java b/modules/core/src/main/java/com/bytedesk/core/channel/ChannelListener.java
index aba37d19fe..fa7270035b 100644
--- a/modules/core/src/main/java/com/bytedesk/core/channel/ChannelListener.java
+++ b/modules/core/src/main/java/com/bytedesk/core/channel/ChannelListener.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-28 11:19:41
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-04-28 11:19:44
+ * @LastEditTime: 2024-06-04 15:31:53
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -25,7 +25,7 @@ public class ChannelListener {
@PostPersist
public void onPostPersist(Channel channel) {
- log.info("onPostPersist: {}", channel.getName());
+ log.info("onPostPersist: {}", channel.getNickname());
}
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/channel/ChannelRequest.java b/modules/core/src/main/java/com/bytedesk/core/channel/ChannelRequest.java
index 6061c79a63..b9768a32a5 100644
--- a/modules/core/src/main/java/com/bytedesk/core/channel/ChannelRequest.java
+++ b/modules/core/src/main/java/com/bytedesk/core/channel/ChannelRequest.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-26 21:07:10
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-04 10:47:25
+ * @LastEditTime: 2024-06-04 15:31:58
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -31,7 +31,7 @@ public class ChannelRequest extends BaseRequest {
private String topic;
- private String name;
+ private String nickname;
private String avatar;
diff --git a/modules/core/src/main/java/com/bytedesk/core/channel/ChannelResponse.java b/modules/core/src/main/java/com/bytedesk/core/channel/ChannelResponse.java
index 1996d25cbe..361fbfea76 100644
--- a/modules/core/src/main/java/com/bytedesk/core/channel/ChannelResponse.java
+++ b/modules/core/src/main/java/com/bytedesk/core/channel/ChannelResponse.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-26 21:07:22
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-04-28 10:55:42
+ * @LastEditTime: 2024-06-04 15:32:03
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -33,7 +33,7 @@ public class ChannelResponse extends BaseResponse {
private String type;
- private String name;
+ private String nickname;
private String avatar;
diff --git a/modules/core/src/main/java/com/bytedesk/core/channel/ChannelService.java b/modules/core/src/main/java/com/bytedesk/core/channel/ChannelService.java
index cd1a049b94..70781db6cb 100644
--- a/modules/core/src/main/java/com/bytedesk/core/channel/ChannelService.java
+++ b/modules/core/src/main/java/com/bytedesk/core/channel/ChannelService.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-26 21:06:12
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-08 10:16:34
+ * @LastEditTime: 2024-06-04 15:32:11
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -73,22 +73,16 @@ public class ChannelService {
if (channelRepository.count() > 0) {
return;
}
-
- // Optional adminOptional = userService.getAdmin();
-
+
ChannelRequest channelRequest = ChannelRequest.builder()
.topic(TopicConsts.TOPIC_SYSTEM_NOTIFICATION)
- .name(I18Consts.I18N_SYSTEM_NOTIFICATION_NAME)
+ .nickname(I18Consts.I18N_SYSTEM_NOTIFICATION_NAME)
.avatar(AvatarConsts.DEFAULT_SYSTEM_NOTIFICATION_AVATAR_URL)
.description(I18Consts.I18N_SYSTEM_NOTIFICATION_DESCRIPTION)
- // .orgUid(adminOptional.get().getOrgUid())
.orgUid(UserConsts.DEFAULT_ORGANIZATION_UID)
.build();
channelRequest.setType(TypeConsts.TYPE_SYSTEM);
create(channelRequest);
- //
-
-
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/config/BytedeskProperties.java b/modules/core/src/main/java/com/bytedesk/core/config/BytedeskProperties.java
index 12e94777d5..9258e4130d 100644
--- a/modules/core/src/main/java/com/bytedesk/core/config/BytedeskProperties.java
+++ b/modules/core/src/main/java/com/bytedesk/core/config/BytedeskProperties.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-30 09:14:39
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-10 15:37:48
+ * @LastEditTime: 2024-06-03 12:08:11
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -14,6 +14,9 @@
*/
package com.bytedesk.core.config;
+import java.util.ArrayList;
+import java.util.List;
+
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@@ -24,20 +27,28 @@ import lombok.Data;
@ConfigurationProperties(prefix = "bytedesk")
public class BytedeskProperties {
- private boolean debug = true;
+ private Boolean debug;
- private String username;
-
- private String password;
-
- private String nickname;
+ // private String username;
private String email;
+ private String password;
+
+ private String passwordDefault;
+
+ private String nickname;
+
private String mobile;
- private String company;
+ private List mobileWhitelist = new ArrayList<>();
+ private String mobileCode;
+
+ private String organizationName;
+
+ private String organizationCode;
+
// private String timezone;
// cors
@@ -57,4 +68,9 @@ public class BytedeskProperties {
private String uploadDir;
private String uploadUrl;
+ //
+ public Boolean isInWhitelist(String mobile) {
+ return this.mobileWhitelist.contains(mobile);
+ }
+
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/config/SecurityConfig.java b/modules/core/src/main/java/com/bytedesk/core/config/SecurityConfig.java
index 91ad8ba688..7178a82b64 100644
--- a/modules/core/src/main/java/com/bytedesk/core/config/SecurityConfig.java
+++ b/modules/core/src/main/java/com/bytedesk/core/config/SecurityConfig.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-05-16 18:19:59
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-19 21:51:00
+ * @LastEditTime: 2024-05-23 20:51:18
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -30,7 +30,7 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
import static org.springframework.security.config.Customizer.withDefaults;
import com.bytedesk.core.rbac.auth.AuthEntryPoint;
-import com.bytedesk.core.rbac.auth.AuthJwtTokenFilter;
+import com.bytedesk.core.rbac.auth.AuthTokenFilter;
import com.bytedesk.core.rbac.user.UserDetailsServiceImpl;
/**
@@ -66,7 +66,7 @@ public class SecurityConfig {
.headers(headers -> headers.frameOptions(frameOptions -> frameOptions.sameOrigin().disable()))
.authenticationProvider(authenticationProvider())
// .oauth2ResourceServer((oauth2) -> oauth2.jwt(withDefaults()))
- .addFilterBefore(authJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
+ .addFilterBefore(authTokenFilter(), UsernamePasswordAuthenticationFilter.class);
//
return http.build();
}
@@ -77,8 +77,8 @@ public class SecurityConfig {
}
@Bean
- public AuthJwtTokenFilter authJwtTokenFilter() {
- return new AuthJwtTokenFilter();
+ public AuthTokenFilter authTokenFilter() {
+ return new AuthTokenFilter();
}
/**
diff --git a/modules/core/src/main/java/com/bytedesk/core/constant/BdConstants.java b/modules/core/src/main/java/com/bytedesk/core/constant/BdConstants.java
index 46d8209d6b..04fda13bd2 100644
--- a/modules/core/src/main/java/com/bytedesk/core/constant/BdConstants.java
+++ b/modules/core/src/main/java/com/bytedesk/core/constant/BdConstants.java
@@ -26,8 +26,7 @@ public class BdConstants {
* Path separator.
*/
public static final String FILE_SEPARATOR = File.separator;
-
- public static final String DEFAULT_USER_DESCRIPTION = "user default description";
+ // public static final String DEFAULT_USER_DESCRIPTION = "user default description";
/**
* 是否私有部署
diff --git a/modules/core/src/main/java/com/bytedesk/core/constant/ClientConsts.java b/modules/core/src/main/java/com/bytedesk/core/constant/ClientConsts.java
index 56907c6b73..9dc1440196 100644
--- a/modules/core/src/main/java/com/bytedesk/core/constant/ClientConsts.java
+++ b/modules/core/src/main/java/com/bytedesk/core/constant/ClientConsts.java
@@ -1,109 +1,109 @@
package com.bytedesk.core.constant;
-/**
- *
- * @author xiaper.io
- */
-public class ClientConsts {
+// /**
+// *
+// * @author xiaper.io
+// */
+// public class ClientConsts {
- // Prevents instantiation
- private ClientConsts() {}
+// // Prevents instantiation
+// private ClientConsts() {}
- // 访客端
- /**
- * 访客pc网站
- */
- public static String CLIENT_WEB = "web";
- /**
- * 访客手机网站
- */
- public static String CLIENT_WAP = "wap";
- /**
- * 访客安卓
- */
- public static String CLIENT_ANDROID = "android";
- /**
- * 访客苹果
- */
- public static String CLIENT_IOS = "ios";
- /**
- * uniapp
- */
- public static String CLIENT_UNIAPP = "uniapp";
- /**
- * Flutter客户端
- */
- public static String CLIENT_FLUTTER = "flutter";
- //
- public static String CLIENT_FLUTTER_ANDROID = "flutter_android";
- public static String CLIENT_FLUTTER_IOS = "flutter_ios";
- public static String CLIENT_FLUTTER_WEB = "flutter_web";
- //
- public static String CLIENT_FLUTTER_ANDROID_SCHOOL = "flutter_android_school";
- public static String CLIENT_FLUTTER_IOS_SCHOOL = "flutter_ios_school";
- public static String CLIENT_FLUTTER_WEB_SCHOOL = "flutter_web_school";
- /**
- * 微信
- */
- public static String CLIENT_WECHAT = "wechat";
- /**
- * 企业微信
- */
- public static String CLIENT_WECHAT_WORK = "wechat_work";
- /**
- * 访客小程序
- */
- public static String CLIENT_WECHAT_MINI = "wechat_mini";
- /**
- * 访客微信公众号
- */
- public static String CLIENT_WECHAT_MP = "wechat_mp";
- /**
- * 微信客服
- */
- public static String CLIENT_WECHAT_KEFU = "wechat_kefu";
- /**
- * 访客微信自定义菜单
- */
- public static String CLIENT_WECHAT_URL = "wechat_url";
+// // 访客端
+// /**
+// * 访客pc网站
+// */
+// public static String CLIENT_WEB = "web";
+// /**
+// * 访客手机网站
+// */
+// public static String CLIENT_WAP = "wap";
+// /**
+// * 访客安卓
+// */
+// public static String CLIENT_ANDROID = "android";
+// /**
+// * 访客苹果
+// */
+// public static String CLIENT_IOS = "ios";
+// /**
+// * uniapp
+// */
+// public static String CLIENT_UNIAPP = "uniapp";
+// /**
+// * Flutter客户端
+// */
+// public static String CLIENT_FLUTTER = "flutter";
+// //
+// public static String CLIENT_FLUTTER_ANDROID = "flutter_android";
+// public static String CLIENT_FLUTTER_IOS = "flutter_ios";
+// public static String CLIENT_FLUTTER_WEB = "flutter_web";
+// //
+// public static String CLIENT_FLUTTER_ANDROID_SCHOOL = "flutter_android_school";
+// public static String CLIENT_FLUTTER_IOS_SCHOOL = "flutter_ios_school";
+// public static String CLIENT_FLUTTER_WEB_SCHOOL = "flutter_web_school";
+// /**
+// * 微信
+// */
+// public static String CLIENT_WECHAT = "wechat";
+// /**
+// * 企业微信
+// */
+// public static String CLIENT_WECHAT_WORK = "wechat_work";
+// /**
+// * 访客小程序
+// */
+// public static String CLIENT_WECHAT_MINI = "wechat_mini";
+// /**
+// * 访客微信公众号
+// */
+// public static String CLIENT_WECHAT_MP = "wechat_mp";
+// /**
+// * 微信客服
+// */
+// public static String CLIENT_WECHAT_KEFU = "wechat_kefu";
+// /**
+// * 访客微信自定义菜单
+// */
+// public static String CLIENT_WECHAT_URL = "wechat_url";
- // 客服端
- /**
- * Windwow客服端
- */
- public static String CLIENT_WINDOW_ADMIN = "window_admin";
- /**
- * MAC客服端
- */
- public static String CLIENT_MAC_ADMIN = "mac_admin";
- /**
- * 安卓手机客服端
- */
- public static String CLIENT_ANDROID_ADMIN = "android_admin";
- /**
- * 苹果手机客服端
- */
- public static String CLIENT_IOS_ADMIN = "ios_admin";
- /**
- * web客服端
- */
- public static String CLIENT_WEB_ADMIN = "web_admin";
- /**
- * 小程序客服端
- */
- public static String CLIENT_WECHAT_MINI_ADMIN = "wechat_mini_admin";
- /**
- * 系统端
- */
- public static String CLIENT_SYSTEM = "system";
- /**
- * 小程序非官方接口,自定义接口
- */
- public static String CLIENT_WECHAT_MINI_STOMP = "wechat_mini_stomp";
+// // 客服端
+// /**
+// * Windwow客服端
+// */
+// public static String CLIENT_WINDOW_ADMIN = "window_admin";
+// /**
+// * MAC客服端
+// */
+// public static String CLIENT_MAC_ADMIN = "mac_admin";
+// /**
+// * 安卓手机客服端
+// */
+// public static String CLIENT_ANDROID_ADMIN = "android_admin";
+// /**
+// * 苹果手机客服端
+// */
+// public static String CLIENT_IOS_ADMIN = "ios_admin";
+// /**
+// * web客服端
+// */
+// public static String CLIENT_WEB_ADMIN = "web_admin";
+// /**
+// * 小程序客服端
+// */
+// public static String CLIENT_WECHAT_MINI_ADMIN = "wechat_mini_admin";
+// /**
+// * 系统端
+// */
+// public static String CLIENT_SYSTEM = "system";
+// /**
+// * 小程序非官方接口,自定义接口
+// */
+// public static String CLIENT_WECHAT_MINI_STOMP = "wechat_mini_stomp";
-}
+// }
diff --git a/modules/core/src/main/java/com/bytedesk/core/constant/I18Consts.java b/modules/core/src/main/java/com/bytedesk/core/constant/I18Consts.java
index 43c39628c5..0c2d1465fc 100644
--- a/modules/core/src/main/java/com/bytedesk/core/constant/I18Consts.java
+++ b/modules/core/src/main/java/com/bytedesk/core/constant/I18Consts.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-26 22:25:47
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-10 15:56:06
+ * @LastEditTime: 2024-06-12 07:07:56
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -16,16 +16,17 @@ package com.bytedesk.core.constant;
// 国际化常量
public class I18Consts {
-
+
private I18Consts() {
}
- // public static final String EN = "en";
+ public static final String EN = "en";
// public static final String ZH = "zh";
+ //
public static final String EN_US = "en-US";
public static final String ZH_CN = "zh-CN";
public static final String ZH_TW = "zh-TW";
-
+
public static final String I18N_PREFIX = "i18n_";
// "文件助手"
public static final String I18N_FILE_ASISTANT_NAME = I18N_PREFIX + "file_asistant";
@@ -34,9 +35,37 @@ public class I18Consts {
// 系统通知
public static final String I18N_SYSTEM_NOTIFICATION_NAME = I18N_PREFIX + "system_notification";
public static final String I18N_SYSTEM_NOTIFICATION_DESCRIPTION = I18N_PREFIX + "system_notification_description";
- //
+ //
public static final String I18N_THREAD_CONTENT_IMAGE = I18N_PREFIX + "thread_content_image";
public static final String I18N_THREAD_CONTENT_FILE = I18N_PREFIX + "thread_content_file";
+ //
+ public static final String I18N_WELCOME_TIP = I18N_PREFIX + "welcome_tip";
+ public static final String I18N_TOP_TIP = I18N_PREFIX + "top_tip";
+ public static final String I18N_LEAVEMSG_TIP = I18N_PREFIX + "leavemsg_tip";
+ //
+ public static final String I18N_WORKGROUP_NICKNAME = I18N_PREFIX + "workgroup_nickname";
+ public static final String I18N_WORKGROUP_DESCRIPTION = I18N_PREFIX + "workgroup_description";
+ //
+ public static final String I18N_AGENT_NICKNAME = I18N_PREFIX + "agent_nickname";
+ public static final String I18N_AGENT_DESCRIPTION = I18N_PREFIX + "agent_description";
+ public static final String I18N_AGENT_OFFLINE = I18N_PREFIX + "agent_offline";
+ public static final String I18N_AGENT_UNAVAILABLE = I18N_PREFIX + "agent_unavailable";
+ public static final String I18N_AGENT_AVAILABLE = I18N_PREFIX + "agent_available";
+ //
+ public static final String I18N_USER_NICKNAME = I18N_PREFIX + "user_nickname";
+ public static final String I18N_USER_DESCRIPTION = I18N_PREFIX + "user_description";
//
+ public static final String I18N_DESCRIPTION = I18N_PREFIX + "description";
+ // "你是一个聪明、对人类有帮助的人工智能,你可以对人类提出的问题给出有用、详细、礼貌的回答"
+ // "智能问答机器人"
+ public static final String I18N_ROBOT_NICKNAME = I18N_PREFIX + "robot_nickname";
+ public static final String I18N_ROBOT_DESCRIPTION = I18N_PREFIX + "robot_description";
+ //
+ public static final String I18N_ROBOT_LLM_PROMPT_ZH_CN = "你是一个聪明、对人类有帮助的人工智能,你可以对人类提出的问题给出有用、详细、礼貌的回答";
+ //
+ public static final String I18N_ADMIN = I18N_PREFIX + "admin";
+ public static final String I18N_ADMIN_DESCRIPTION = I18N_PREFIX + "admin_description";
+
+
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/constant/RedisConsts.java b/modules/core/src/main/java/com/bytedesk/core/constant/RedisConsts.java
index e0eedaca1a..66e8aee299 100644
--- a/modules/core/src/main/java/com/bytedesk/core/constant/RedisConsts.java
+++ b/modules/core/src/main/java/com/bytedesk/core/constant/RedisConsts.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-27 10:55:25
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-04-16 12:39:23
+ * @LastEditTime: 2024-06-07 14:47:38
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
diff --git a/modules/core/src/main/java/com/bytedesk/core/constant/RouteConsts.java b/modules/core/src/main/java/com/bytedesk/core/constant/RouteConsts.java
deleted file mode 100644
index 954590e1a9..0000000000
--- a/modules/core/src/main/java/com/bytedesk/core/constant/RouteConsts.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * @Author: jackning 270580156@qq.com
- * @Date: 2024-02-26 12:20:17
- * @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-02-26 12:20:22
- * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
- * Please be aware of the BSL license restrictions before installing Bytedesk IM –
- * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
- * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
- * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
- * contact: 270580156@qq.com
- * 联系:270580156@qq.com
- * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
- */
-package com.bytedesk.core.constant;
-
-/**
- *
- * @author xiaper.io
- */
-public class RouteConsts {
-
- // Prevents instantiation
- private RouteConsts() {
- }
-
- /**
- * 轮询分配
- * Round-robin
- */
- public static final String ROUTE_TYPE_ROBIN = "robin";
- /**
- * 当日内按照接待个数平均分配,少者优先
- * 0:点清空前一天,并开始新的一天计数
- */
- public static final String ROUTE_TYPE_AVERAGE = "average";
- /**
- * 当前饱和度,饱和度越低,空缺位置越多,优先分配
- */
- public static final String ROUTE_TYPE_IDLE = "idle";
- /**
- * 当前正在进行中对话数量,少者优先
- */
- public static final String ROUTE_TYPE_LESS = "less";
- /**
- * 广播给所有客服,客服抢单
- */
- public static final String ROUTE_TYPE_BOARDCAST = "broadcast";
- /**
- * 熟客优先,最近会话优先分配
- */
- // public static final String ROUTE_TYPE_RECENT = "recent";
- /**
- * TODO: 智能分配,还没有想清楚,待后续完善
- */
- // public static final String ROUTE_TYPE_SMART = "smart";
- /**
- * TODO: 根据客服满意度评分等其他因素自动分配
- */
- // public static final String ROUTE_TYPE_RATE = "rate";
-
-}
diff --git a/modules/core/src/main/java/com/bytedesk/core/constant/StatusConsts.java b/modules/core/src/main/java/com/bytedesk/core/constant/StatusConsts.java
deleted file mode 100644
index 74909585f0..0000000000
--- a/modules/core/src/main/java/com/bytedesk/core/constant/StatusConsts.java
+++ /dev/null
@@ -1,255 +0,0 @@
-package com.bytedesk.core.constant;
-
-/**
- *
- * @author xiaper.io
- */
-public class StatusConsts {
-
- // Prevents instantiation
- private StatusConsts() {}
-
- /**
- * app、网站已经上线
- */
- public static final String APP_STATUS_RELEASE = "release";
- /**
- * 开发对接中...
- */
- public static final String APP_STATUS_DEBUG = "debug";
- /**
- * 已上线,开发新版本中
- */
- public static final String APP_STATUS_VERSION = "version";
-
-
- /**
- * 消息发送状态:
- *
- * 1. 发送中
- */
- public static final String MESSAGE_STATUS_SENDING = "sending";
- /**
- * 2. 已经存储到服务器
- */
- public static final String MESSAGE_STATUS_STORED = "stored";
- /**
- * 3. 对方已收到
- */
- public static final String MESSAGE_STATUS_RECEIVED = "received";
- /**
- * 4. 对方已读
- */
- public static final String MESSAGE_STATUS_READ = "read";
- /**
- * 5. 发送错误
- */
- public static final String MESSAGE_STATUS_ERROR = "error";
- /**
- * 6. 阅后即焚已销毁
- */
- public static final String MESSAGE_STATUS_DESTROYED = "destroyed";
- /**
- * 7. 消息撤回
- */
- public static final String MESSAGE_STATUS_RECALL = "recall";
- /**
- * 8. 对方拒收
- */
- public static final String MESSAGE_STATUS_REJECT = "reject";
-
-
- /**
- * 用户在线状态:
- */
- /**
- * 跟服务器建立长连接
- */
- public static final String USER_STATUS_CONNECTED = "connected";
- /**
- * 断开长连接
- */
- public static final String USER_STATUS_DISCONNECTED = "disconnected";
- /**
- * 在线状态
- */
- public static final String USER_STATUS_ONLINE = "online";
- /**
- * 离线状态
- */
- public static final String USER_STATUS_OFFLINE = "offline";
- /**
- * 忙
- */
- public static final String USER_STATUS_BUSY = "busy";
- /**
- * 离开
- */
- public static final String USER_STATUS_AWAY = "away";
- /**
- * 登出
- */
- public static final String USER_STATUS_LOGOUT = "logout";
- /**
- * 登录
- */
- public static final String USER_STATUS_LOGIN = "login";
- /**
- * 离开
- */
- public static final String USER_STATUS_LEAVE = "leave";
- /**
- * 话后
- */
- public static final String USER_STATUS_AFTER = "after";
- /**
- * 就餐
- */
- public static final String USER_STATUS_EAT = "eat";
- /**
- * 小休
- */
- public static final String USER_STATUS_REST = "rest";
- /**
- * 签入
- */
- public static final String USER_STATUS_SIGN_IN = "sign_in";
- /**
- * 签出
- */
- public static final String USER_STATUS_SIGN_OUT = "sign_out";
-
-
- /**
- * 排队状态: 排队中
- */
- public static final String QUEUE_STATUS_QUEUING = "queuing";
- /**
- * 已接入
- */
- public static final String QUEUE_STATUS_ACCEPTED = "accepted";
- /**
- * 已忽略
- */
- public static final String QUEUE_STATUS_IGNORED = "ignored";
- /**
- * 已离开
- */
- public static final String QUEUE_STATUS_LEAVED = "leaved";
- /**
- * 超时
- */
- public static final String QUEUE_STATUS_TIMEOUT = "timeout";
-
-
- /**
- * 留言状态: 未被领取
- */
- public static final String LEAVE_MESSAGE_STATUS_UNCLAIMED = "unclaimed";
- /**
- * 已领取
- */
- public static final String LEAVE_MESSAGE_STATUS_CLAIMED = "claimed";
- /**
- * 已小结
- */
- public static final String LEAVE_MESSAGE_STATUS_SUMMARIZED = "summarized";
-
- /**
- * 支付:等待支付、支付成功、支付失败
- */
- public static final String PAY_STATUS_WAITING = "waiting";
- public static final String PAY_STATUS_SUCCESS = "success";
- public static final String PAY_STATUS_FAILED = "failed";
-
- /**
- * iOS app status
- */
- public static final String IOS_BUILD_DEBUG = "debug";
- public static final String IOS_BUILD_RELEASE = "release";
-
- /**
- * 工单状态(客服角度): 待认领、待回复、处理中、待评价、已解决、已忽略、已关闭
- */
- public static final String TICKET_STATUS_UNCLAIM = "unclaim";
- // public static final String TICKET_STATUS_WAITING = "waiting";
- public static final String TICKET_STATUS_TO_BE_REPLIED = "to_be_replied";
- public static final String TICKET_STATUS_PROCESSING = "processing";
- // public static final String TICKET_STATUS_TO_BE_RATED = "to_be_rated";
- public static final String TICKET_STATUS_DONE = "done"; // 客服解决
- public static final String TICKET_STATUS_IGNORE = "ignore"; // 客服忽略
- public static final String TICKET_STATUS_CLOSED = "closed"; // 访客关闭
-
- /**
- * 瀑布状态:发布、审核中、下线
- */
- public static final String WATERFALL_STATUS_ON = "on";
- public static final String WATERFALL_STATUS_WAITING = "waiting";
- public static final String WATERFALL_STATUS_OFF = "off";
-
- /**
- * 学校状态:审核中、被拒绝、审核通过
- */
- public static final String SCHOOL_STATUS_WAITING = "waiting";
- public static final String SCHOOL_STATUS_REJECT = "reject";
- public static final String SCHOOL_STATUS_APPROVE = "approve";
-
- /**
- * 课程状态:在售、待售、下架
- */
- public static final String COURSE_STATUS_ON = "on";
- public static final String COURSE_STATUS_WAITING = "waiting";
- public static final String COURSE_STATUS_OFF = "off";
-
- /**
- * 教师状态
- */
- public static final String TEACHER_STATUS_ON = "on";
- public static final String TEACHER_STATUS_OFF = "off";
-
- /**
- * 预约状态: 提交待确认,已确认,已取消
- */
- public static final String APPOINT_STATUS_PENDING = "pending";
- public static final String APPOINT_STATUS_CONFIRM = "confirmed";
- public static final String APPOINT_STATUS_CANCEL = "canceled";
-
- /**
- * 好友关系:未添加、已发送待对方同意、好友、已删除、已拉黑
- */
- public static final String FRIEND_STATUS_NO = "no";
- public static final String FRIEND_STATUS_SEND = "send";
- public static final String FRIEND_STATUS_OK = "ok";
- public static final String FRIEND_STATUS_DELETE = "delete";
- public static final String FRIEND_STATUS_BLOCK = "block";
-
- /**
- * 来源:附近、通讯录、扫一扫、搜索
- */
- public static final String FRIEND_SOURCE_NEARBY = "nearby";
- public static final String FRIEND_SOURCE_ADDRESS = "address";
- public static final String FRIEND_SOURCE_SCAN = "scan";
- public static final String FRIEND_SOURCE_SEARCH = "search";
-
- /**
- * FAQ问答状态:已发布、未发布
- */
- public static final String ANSWER_STATUS_PUBLISHED = "published";
- public static final String ANSWER_STATUS_UNPUBLISHED = "unpublished";
-
- // 同事和群组会话初始值为init
- public static final String THREAD_STATUS_INIT = "init";
- // 只有客服会话会有open
- public static final String THREAD_STATUS_OPEN = "open";
- public static final String THREAD_STATUS_CLOSED_AUTO = "closed_auto";
- public static final String THREAD_STATUS_CLOSED_AGENT = "closed_agent";
- // 发送验证码状态
- public static final String CODE_STATUS_PENDING = "pending";
- public static final String CODE_STATUS_CONFIRM = "confirmed";
- public static final String CODE_STATUS_EXPIRED = "expired";
-
-}
-
-
-
-
diff --git a/modules/core/src/main/java/com/bytedesk/core/constant/ThreadTypeConsts.java b/modules/core/src/main/java/com/bytedesk/core/constant/ThreadTypeConsts.java
index 31bdb50a20..0ee702bdcf 100644
--- a/modules/core/src/main/java/com/bytedesk/core/constant/ThreadTypeConsts.java
+++ b/modules/core/src/main/java/com/bytedesk/core/constant/ThreadTypeConsts.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-02-22 16:01:14
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-04-30 14:43:37
+ * @LastEditTime: 2024-05-29 16:44:02
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -14,22 +14,22 @@
*/
package com.bytedesk.core.constant;
-public class ThreadTypeConsts {
+// public class ThreadTypeConsts {
- private ThreadTypeConsts() {
- }
+// private ThreadTypeConsts() {
+// }
- /**
- * thread type
- */
- public static final String APPOINTED = "appointed";
- public static final String WORKGROUP = "workgroup";
- public static final String MEMBER = "member";
- public static final String GROUP = "group";
- public static final String ROBOT = "robot";
- public static final String LEAVEMSG = "leavemsg";
- public static final String FEEDBACK = "feedback";
- public static final String ASISTANT = "assistant";
- public static final String CHANNEL = "channel";
- public static final String LOCAL = "local";
-}
+// /**
+// * thread type
+// */
+// public static final String APPOINTED = "appointed";
+// public static final String WORKGROUP = "workgroup";
+// public static final String MEMBER = "member";
+// public static final String GROUP = "group";
+// public static final String ROBOT = "robot";
+// public static final String LEAVEMSG = "leavemsg";
+// public static final String FEEDBACK = "feedback";
+// public static final String ASISTANT = "assistant";
+// public static final String CHANNEL = "channel";
+// public static final String LOCAL = "local";
+// }
diff --git a/modules/core/src/main/java/com/bytedesk/core/constant/TypeConsts.java b/modules/core/src/main/java/com/bytedesk/core/constant/TypeConsts.java
index e08cb26d73..2d8ad5d3f1 100644
--- a/modules/core/src/main/java/com/bytedesk/core/constant/TypeConsts.java
+++ b/modules/core/src/main/java/com/bytedesk/core/constant/TypeConsts.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-29 16:21:24
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-16 11:56:53
+ * @LastEditTime: 2024-06-07 14:51:02
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -23,66 +23,57 @@ public class TypeConsts {
public static final String TYPE_MOBILE = "mobile";
public static final String TYPE_EMAIL = "email";
+ //
+ public static final String SUPER = "SUPER";
+ public static final String ADMIN = "ADMIN";
+ public static final String HR = "HR";
+ public static final String ORG = "ORG";
+ public static final String IT = "IT";
+ public static final String MONEY = "MONEY";
+ public static final String MARKETING = "MARKETING";
+ public static final String SALES = "SALES";
+ public static final String CUSTOMER_SERVICE = "CS";
+
// ROLES - 角色
public static final String ROLE_PREFIX = "ROLE_";
-
// super - 超级管理员
- public static final String ROLE_SUPER = "ROLE_SUPER";
- public static final String AUTHORITY_SUPER = "SUPER";
-
+ public static final String ROLE_SUPER = ROLE_PREFIX + SUPER;
// admin - 管理员
- public static final String ROLE_ADMIN = "ROLE_ADMIN";
- public static final String AUTHORITY_ADMIN = "ADMIN";
-
+ public static final String ROLE_ADMIN = ROLE_PREFIX + ADMIN;
// hr - 人事
- public static final String ROLE_HR = "ROLE_HR";
- public static final String AUTHORITY_HR = "HR";
-
+ public static final String ROLE_HR = ROLE_PREFIX + HR;
// org - 行政
- public static final String ROLE_ORG = "ROLE_ORG";
- public static final String AUTHORITY_ORG = "ORG";
-
+ public static final String ROLE_ORG = ROLE_PREFIX + ORG;
// it - IT
- public static final String ROLE_IT = "ROLE_IT";
- public static final String AUTHORITY_IT = "IT";
-
+ public static final String ROLE_IT = ROLE_PREFIX + IT;
// money - 财务
- public static final String ROLE_MONEY = "ROLE_MONEY";
- public static final String AUTHORITY_MONEY = "MONEY";
-
+ public static final String ROLE_MONEY = ROLE_PREFIX + MONEY;
// marketing - 市场
- public static final String ROLE_MARKETING = "ROLE_MARKETING";
- public static final String AUTHORITY_MARKETING = "MARKETING";
-
+ public static final String ROLE_MARKETING = ROLE_PREFIX + MARKETING;
// sales - 销售
- public static final String ROLE_SALES = "ROLE_SALES";
- public static final String AUTHORITY_SALES = "SALES";
-
+ public static final String ROLE_SALES = ROLE_PREFIX + SALES;
// customer service - 客服
- public static final String ROLE_CUSTOMER_SERVICE = "ROLE_CS";
- public static final String AUTHORITY_CUSTOMER_SERVICE = "CS";
+ public static final String ROLE_CUSTOMER_SERVICE = ROLE_PREFIX + CUSTOMER_SERVICE;
/// 部门
+ // 管理员
+ public static final String DEPT_PREFIX = "DEPT_";
+ public static final String DEPT_ADMIN = DEPT_PREFIX + ADMIN;
+
// hr - 人事
- public static final String DEPT_HR = "DEPT_HR";
-
+ public static final String DEPT_HR = DEPT_PREFIX + HR;
// org - 行政
- public static final String DEPT_ORG = "DEPT_ORG";
-
+ public static final String DEPT_ORG = DEPT_PREFIX + ORG;
// it - IT
- public static final String DEPT_IT = "DEPT_IT";
-
+ public static final String DEPT_IT = DEPT_PREFIX + IT;
// money - 财务
- public static final String DEPT_MONEY = "DEPT_MONEY";
-
+ public static final String DEPT_MONEY = DEPT_PREFIX + MONEY;
// marketing - 市场
- public static final String DEPT_MARKETING = "DEPT_MARKETING";
-
+ public static final String DEPT_MARKETING = DEPT_PREFIX + MARKETING;
// sales - 销售
- public static final String DEPT_SALES = "DEPT_SALES";
-
+ public static final String DEPT_SALES = DEPT_PREFIX + SALES;
// customer service - 客服
- public static final String DEPT_CUSTOMER_SERVICE = "DEPT_CS";
+ public static final String DEPT_CUSTOMER_SERVICE = DEPT_PREFIX + CUSTOMER_SERVICE;
//
public static final String SEND_MOBILE_CODE_TYPE_LOGIN = "login";
@@ -90,7 +81,6 @@ public class TypeConsts {
public static final String SEND_MOBILE_CODE_TYPE_FORGET = "forget";
public static final String SEND_MOBILE_CODE_TYPE_VERIFY = "verify";
-
/**
* region类型, 代码长度分别为:省 2、市 4、区/县 6、镇 9
*/
@@ -99,5 +89,16 @@ public class TypeConsts {
public static final String REGION_TYPE_COUNTY = "county";
public static final String REGION_TYPE_TOWN = "town";
-
+ //
+ public static final String COLUMN_TYPE_TEXT = "TEXT"; // length = 65534
+ public static final String COLUMN_TYPE_JSON = "json"; //
+ public static final String COLUMN_NAME_TYPE = "by_type";
+ public static final String COLUMN_NAME_USER = "by_user";
+
+ //
+ // public static final String ROBOT_TYPE_SERVICE = "service";
+
+ //
+ public static final String ACTION_TYPE_FAILED = "failed";
+ public static final String ACTION_TYPE_LOG = "log";
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/constant/UserConsts.java b/modules/core/src/main/java/com/bytedesk/core/constant/UserConsts.java
index b58d770087..083da9fb30 100644
--- a/modules/core/src/main/java/com/bytedesk/core/constant/UserConsts.java
+++ b/modules/core/src/main/java/com/bytedesk/core/constant/UserConsts.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-02-26 12:21:02
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-08 10:24:18
+ * @LastEditTime: 2024-06-05 12:57:52
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -52,8 +52,11 @@ public class UserConsts {
// 默认组织uid
public static final String DEFAULT_ORGANIZATION_UID = "default_organization_uid";
+ public static final String DEFAULT_AGENT_UID = "default_agent_uid";
+ public static final String DEFAULT_WORKGROUP_UID = "default_wg_uid";
+ public static final String DEFAULT_ROBOT_UID = "default_robot_uid";
public static final String DEFAULT_FILE_ASISTANT_UID = "default_file_asistant_uid";
-
+ public static final String DEFAULT_SYSTEM_NOTIFICATION_UID = "default_system_notification_uid";
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/enums/ClientEnum.java b/modules/core/src/main/java/com/bytedesk/core/enums/ClientEnum.java
new file mode 100644
index 0000000000..e773a0ba57
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/enums/ClientEnum.java
@@ -0,0 +1,54 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-05-25 13:07:20
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-06 11:40:46
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.enums;
+
+
+public enum ClientEnum {
+ SYSTEM("system"),
+ WEB("web"),
+ H5("h5"),
+ IOS("ios"),
+ ANDROID("android"),
+ FLUTTER_WEB("flutter_web"),
+ FLUTTER_ANDROID("flutter_android"),
+ FLUTTER_IOS("flutter_ios"),
+ UNI_WEB("uni_web"),
+ UNI_ANDROID("uni_android"),
+ UNI_IOS("uni_ios"),
+ WECHAT_MINI("wechat_mini"),
+ WECHAT_MP("wechat_mp"),
+ WECHAT_WORK("wechat_work"),
+ WECHAT_KEFU("wechat_kefu");
+
+ private final String value;
+
+ ClientEnum(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ // 根据字符串查找对应的枚举常量
+ public static ClientEnum fromValue(String value) {
+ for (ClientEnum type : ClientEnum.values()) {
+ if (type.getValue().equalsIgnoreCase(value)) {
+ return type;
+ }
+ }
+ throw new IllegalArgumentException("No enum constant with value: " + value);
+ }
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/enums/LanguageEnum.java b/modules/core/src/main/java/com/bytedesk/core/enums/LanguageEnum.java
new file mode 100644
index 0000000000..abba4bc96a
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/enums/LanguageEnum.java
@@ -0,0 +1,41 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-06-07 14:19:24
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-07 14:20:31
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.enums;
+
+public enum LanguageEnum {
+ EN("en"),
+ ZH_CN("zh-cn"),
+ ZH_TW("zh-tw");
+
+ private final String value;
+
+ LanguageEnum(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ // 根据字符串查找对应的枚举常量
+ public static LanguageEnum fromValue(String value) {
+ for (LanguageEnum type : LanguageEnum.values()) {
+ if (type.getValue().equalsIgnoreCase(value)) {
+ return type;
+ }
+ }
+ throw new IllegalArgumentException("No enum constant with value: " + value);
+ }
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/event/BytedeskEventListener.java b/modules/core/src/main/java/com/bytedesk/core/event/BytedeskEventListener.java
new file mode 100644
index 0000000000..84dfc1ed11
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/event/BytedeskEventListener.java
@@ -0,0 +1,31 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-06-04 12:59:46
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-04 13:00:20
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.event;
+
+import org.springframework.context.event.EventListener;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+
+import com.bytedesk.core.utils.JsonResult;
+
+@Component
+public class BytedeskEventListener {
+
+ @EventListener
+ public ResponseEntity> onEmailAlreadyExistsEvent(EmailAlreadyExistsEvent event) {
+ return ResponseEntity.ok().body(JsonResult.error("Email " + event.getEmail() + " already exists, please login or use another one"));
+ }
+
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/event/BytedeskEventPublisher.java b/modules/core/src/main/java/com/bytedesk/core/event/BytedeskEventPublisher.java
index c9486f2a83..d59c6abe0a 100644
--- a/modules/core/src/main/java/com/bytedesk/core/event/BytedeskEventPublisher.java
+++ b/modules/core/src/main/java/com/bytedesk/core/event/BytedeskEventPublisher.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-02-23 14:42:58
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-04-23 08:55:55
+ * @LastEditTime: 2024-06-04 13:02:44
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -15,10 +15,20 @@
package com.bytedesk.core.event;
import org.springframework.context.ApplicationEventPublisher;
-import org.springframework.scheduling.annotation.Async;
+// import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
+import com.bytedesk.core.action.ActionEvent;
+import com.bytedesk.core.action.ActionRequest;
+import com.bytedesk.core.message.MessageBytesEvent;
+import com.bytedesk.core.message.MessageJsonEvent;
+import com.bytedesk.core.quartz.QuartzFiveSecondEvent;
+import com.bytedesk.core.rbac.organization.Organization;
+import com.bytedesk.core.rbac.organization.OrganizationCreateEvent;
import com.bytedesk.core.thread.Thread;
+import com.bytedesk.core.thread.ThreadCreateEvent;
+import com.bytedesk.core.thread.ThreadUpdateEvent;
+
import lombok.AllArgsConstructor;
@Component
@@ -27,50 +37,63 @@ public class BytedeskEventPublisher {
private final ApplicationEventPublisher applicationEventPublisher;
- @Async
+
public void publishMessageBytesEvent(byte[] messageBytes) {
applicationEventPublisher.publishEvent(new MessageBytesEvent(this, messageBytes));
}
- @Async
+
public void publishMessageJsonEvent(String json) {
applicationEventPublisher.publishEvent(new MessageJsonEvent(this, json));
}
- @Async
+
public void publishQuartzFiveSecondEvent() {
applicationEventPublisher.publishEvent(new QuartzFiveSecondEvent(this));
}
- @Async
+
public void publishMqttConnectedEvent(String client) {
applicationEventPublisher.publishEvent(new MqttConnectedEvent(this, client));
}
- @Async
+
public void publishMqttDisconnectedEvent(String client) {
applicationEventPublisher.publishEvent(new MqttDisconnectedEvent(this, client));
}
- // @Async
- // public void publishMqttSubscribeEvent(String uid, String topic) {
- // applicationEventPublisher.publishEvent(new MqttSubscribeEvent(this, uid, topic));
- // }
- // @Async
- // public void publishMqttUnsubscribeEvent(String uid, String topic) {
- // applicationEventPublisher.publishEvent(new MqttUnsubscribeEvent(this, uid, topic));
- // }
+ public void publishMqttSubscribeEvent(String topic, String clientId) {
+ applicationEventPublisher.publishEvent(new MqttSubscribeEvent(this, topic, clientId));
+ }
+
+
+ public void publishMqttUnsubscribeEvent(String topic, String clientId) {
+ applicationEventPublisher.publishEvent(new MqttUnsubscribeEvent(this, topic, clientId));
+ }
+
- @Async
public void publishThreadCreateEvent(Thread thread) {
applicationEventPublisher.publishEvent(new ThreadCreateEvent(this, thread));
}
- @Async
+
public void publishThreadUpdateEvent(Thread thread) {
applicationEventPublisher.publishEvent(new ThreadUpdateEvent(this, thread));
}
+ public void publishActionEvent(ActionRequest actionRequest) {
+ applicationEventPublisher.publishEvent(new ActionEvent(this, actionRequest));
+ }
+
+
+ public void publishOrganizationCreateEvent(Organization organization) {
+ applicationEventPublisher.publishEvent(new OrganizationCreateEvent(organization));
+ }
+
+ public void publishEmailAlreadyExistsEvent(String email) {
+ applicationEventPublisher.publishEvent(new EmailAlreadyExistsEvent(this, email));
+ }
+
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/event/EmailAlreadyExistsEvent.java b/modules/core/src/main/java/com/bytedesk/core/event/EmailAlreadyExistsEvent.java
new file mode 100644
index 0000000000..015b42c3df
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/event/EmailAlreadyExistsEvent.java
@@ -0,0 +1,33 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-06-04 12:58:38
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-04 12:58:40
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.event;
+
+import org.springframework.context.ApplicationEvent;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class EmailAlreadyExistsEvent extends ApplicationEvent {
+
+ private final String email;
+
+ public EmailAlreadyExistsEvent(Object source, String email) {
+ super(source);
+ this.email = email;
+ }
+
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/event/MqttSubscribeEvent.java b/modules/core/src/main/java/com/bytedesk/core/event/MqttSubscribeEvent.java
index 9ca01db61a..91d15574d5 100644
--- a/modules/core/src/main/java/com/bytedesk/core/event/MqttSubscribeEvent.java
+++ b/modules/core/src/main/java/com/bytedesk/core/event/MqttSubscribeEvent.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-02-23 14:43:57
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-04-16 10:16:12
+ * @LastEditTime: 2024-06-01 10:17:40
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -14,22 +14,21 @@
*/
package com.bytedesk.core.event;
-// import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ApplicationEvent;
-// import lombok.Data;
-// import lombok.EqualsAndHashCode;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
-// @Data
-// @EqualsAndHashCode(callSuper = false)
-// public class MqttSubscribeEvent extends ApplicationEvent {
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class MqttSubscribeEvent extends ApplicationEvent {
-// private String uid;
-// private String topic;
+ private String topic;
+ private String clientId;
-// public MqttSubscribeEvent(Object source, String uid, String topic) {
-// super(source);
-// this.uid = uid;
-// this.topic = topic;
-// }
-
-// }
+ public MqttSubscribeEvent(Object source, String topic, String clientId) {
+ super(source);
+ this.topic = topic;
+ this.clientId = clientId;
+ }
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/event/MqttUnsubscribeEvent.java b/modules/core/src/main/java/com/bytedesk/core/event/MqttUnsubscribeEvent.java
index ffc9a166a0..e1d478e350 100644
--- a/modules/core/src/main/java/com/bytedesk/core/event/MqttUnsubscribeEvent.java
+++ b/modules/core/src/main/java/com/bytedesk/core/event/MqttUnsubscribeEvent.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-02-23 14:43:57
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-04-16 10:16:17
+ * @LastEditTime: 2024-06-01 10:18:09
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -14,22 +14,21 @@
*/
package com.bytedesk.core.event;
-// import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ApplicationEvent;
-// import lombok.Data;
-// import lombok.EqualsAndHashCode;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
-// @Data
-// @EqualsAndHashCode(callSuper = false)
-// public class MqttUnsubscribeEvent extends ApplicationEvent {
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class MqttUnsubscribeEvent extends ApplicationEvent {
-// private String uid;
-// private String topic;
+ private String topic;
+ private String clientId;
-// public MqttUnsubscribeEvent(Object source, String uid, String topic) {
-// super(source);
-// this.uid = uid;
-// this.topic = topic;
-// }
-
-// }
+ public MqttUnsubscribeEvent(Object source, String topic, String clientId) {
+ super(source);
+ this.topic = topic;
+ this.clientId = clientId;
+ }
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/exception/EmailExistsException.java b/modules/core/src/main/java/com/bytedesk/core/exception/EmailExistsException.java
index ec1d9920d7..bc07e3958e 100644
--- a/modules/core/src/main/java/com/bytedesk/core/exception/EmailExistsException.java
+++ b/modules/core/src/main/java/com/bytedesk/core/exception/EmailExistsException.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-26 09:28:30
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-04-26 09:58:48
+ * @LastEditTime: 2024-06-03 19:18:43
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -16,7 +16,7 @@ package com.bytedesk.core.exception;
public class EmailExistsException extends BaseException {
- private static final long serialVersionUID = 5543722167L;
+ private static final long serialVersionUID = 1L;
public EmailExistsException(String message) {
super(message);
diff --git a/modules/core/src/main/java/com/bytedesk/core/exception/GlobalControllerAdvice.java b/modules/core/src/main/java/com/bytedesk/core/exception/GlobalControllerAdvice.java
index 969724e609..4bea57c794 100644
--- a/modules/core/src/main/java/com/bytedesk/core/exception/GlobalControllerAdvice.java
+++ b/modules/core/src/main/java/com/bytedesk/core/exception/GlobalControllerAdvice.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-26 09:31:29
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-13 21:29:30
+ * @LastEditTime: 2024-06-11 16:28:00
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -79,10 +79,20 @@ public class GlobalControllerAdvice {
@ExceptionHandler(NoResourceFoundException.class)
public ResponseEntity> handleNoResourceFoundException(NoResourceFoundException e) {
return ResponseEntity.ok().body(JsonResult.error(
- "Api Resource not found, or It's a vip api, you should contact 270580156@qq.com or visit http://www.weiyuai.cn",
+ e.getMessage(),
404));
+ // // 如果你确定要进行后端跳转,并且你的应用支持这种做法,你可以使用以下方式:
+ // String redirectUrl = "/error/404.html";
+ // // 使用HttpStatus.SEE_OTHER(303)来表示重定向
+ // // 也可以使用HttpStatus.FOUND(302),但303更明确地表示应使用GET方法重定向
+ // return ResponseEntity.status(HttpStatus.SEE_OTHER).location(URI.create(redirectUrl)).build();
}
+ @ExceptionHandler(RuntimeException.class)
+ public ResponseEntity> handleRuntimeException(RuntimeException e) {
+ return ResponseEntity.ok().body(JsonResult.error(e.getMessage()));
+ }
+
@ExceptionHandler(BadCredentialsException.class)
public ResponseEntity> handleBadCredentialsException(BadCredentialsException e) {
return ResponseEntity.ok().body(JsonResult.error("Username or password is incorrect"));
diff --git a/modules/core/src/main/java/com/bytedesk/core/exception/MobileExistsException.java b/modules/core/src/main/java/com/bytedesk/core/exception/MobileExistsException.java
index b3ba445b2e..76b5c2be7b 100644
--- a/modules/core/src/main/java/com/bytedesk/core/exception/MobileExistsException.java
+++ b/modules/core/src/main/java/com/bytedesk/core/exception/MobileExistsException.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-26 09:28:30
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-04-26 09:59:04
+ * @LastEditTime: 2024-06-03 19:18:50
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -16,7 +16,7 @@ package com.bytedesk.core.exception;
public class MobileExistsException extends BaseException {
- private static final long serialVersionUID = -873386350L;
+ private static final long serialVersionUID = 1L;
public MobileExistsException(String message) {
super(message);
diff --git a/modules/core/src/main/java/com/bytedesk/core/exception/NotFoundException.java b/modules/core/src/main/java/com/bytedesk/core/exception/NotFoundException.java
index ed55e67961..a1f6fbda65 100644
--- a/modules/core/src/main/java/com/bytedesk/core/exception/NotFoundException.java
+++ b/modules/core/src/main/java/com/bytedesk/core/exception/NotFoundException.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-26 12:35:08
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-04-26 12:35:10
+ * @LastEditTime: 2024-06-03 19:18:59
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -19,7 +19,7 @@ package com.bytedesk.core.exception;
*/
public class NotFoundException extends BaseException {
- private static final long serialVersionUID = -984846602L;
+ private static final long serialVersionUID = 1L;
public NotFoundException(String message) {
super(message);
diff --git a/modules/core/src/main/java/com/bytedesk/core/ip/Ip.java b/modules/core/src/main/java/com/bytedesk/core/ip/Ip.java
index dafc751884..37b3efbcda 100644
--- a/modules/core/src/main/java/com/bytedesk/core/ip/Ip.java
+++ b/modules/core/src/main/java/com/bytedesk/core/ip/Ip.java
@@ -14,7 +14,10 @@
*/
package com.bytedesk.core.ip;
+import java.util.Date;
+
import com.bytedesk.core.base.BaseEntity;
+import com.bytedesk.core.constant.TypeConsts;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
@@ -35,15 +38,17 @@ import lombok.experimental.Accessors;
@NoArgsConstructor
@Table(name = "core_ip")
public class Ip extends BaseEntity {
-
private String ip;
+ // private String ipLocation;
+
// 1: black
- @Column(name = "by_type")
+ @Column(name = TypeConsts.COLUMN_NAME_TYPE)
private String type;
- // TODO: time duration
+ // time duration
+ private Date blockUntilDate;
/** belong to org */
private String orgUid;
diff --git a/modules/core/src/main/java/com/bytedesk/core/ip/IpInterceptor.java b/modules/core/src/main/java/com/bytedesk/core/ip/IpInterceptor.java
index 4c45162fe7..25b92c74a5 100644
--- a/modules/core/src/main/java/com/bytedesk/core/ip/IpInterceptor.java
+++ b/modules/core/src/main/java/com/bytedesk/core/ip/IpInterceptor.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-05-17 12:53:46
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-19 18:50:18
+ * @LastEditTime: 2024-05-23 23:34:16
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -38,7 +38,8 @@ public class IpInterceptor implements HandlerInterceptor {
throws Exception {
String ip = ipService.getIp(request);
- log.info("IpInterceptor ip: {}", ip);
+ String ipLocation = ipService.getIpLocation(ip);
+ log.info("IpInterceptor ip: {}, ipLocation {}", ip, ipLocation);
// TODO: blacklist check
// if (ipService.isIpInBlackList(ip)) {
diff --git a/modules/core/src/main/java/com/bytedesk/core/ip/IpService.java b/modules/core/src/main/java/com/bytedesk/core/ip/IpService.java
index 86ff7e5b0f..d7666a0b4d 100644
--- a/modules/core/src/main/java/com/bytedesk/core/ip/IpService.java
+++ b/modules/core/src/main/java/com/bytedesk/core/ip/IpService.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-16 13:28:03
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-05 17:00:38
+ * @LastEditTime: 2024-06-05 16:02:08
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -17,6 +17,8 @@ package com.bytedesk.core.ip;
import org.lionsoul.ip2region.xdb.Searcher;
import org.springframework.stereotype.Service;
+import com.bytedesk.core.uid.UidUtils;
+
import jakarta.servlet.http.HttpServletRequest;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -31,8 +33,11 @@ public class IpService {
private final Searcher searcher;
+ private final UidUtils uidUtils;
+
/**
* 获取客户端ip
+ *
* @param request
* @return
*/
@@ -43,6 +48,7 @@ public class IpService {
/**
* location: "国家|区域|省份|城市|ISP"
* location: "中国|0|湖北省|武汉市|联通"
+ *
* @param ip
* @return
*/
@@ -60,4 +66,25 @@ public class IpService {
return getIpLocation(ip);
}
+ public String createVisitorNickname(HttpServletRequest request) {
+
+ String location = getIpLocation(request);
+ // TODO: 修改昵称后缀数字为从1~递增
+ String randomId = uidUtils.getCacheSerialUid();//.substring(11, 15);
+
+ // location: "国家|区域|省份|城市|ISP"
+ // location: "中国|0|湖北省|武汉市|联通"
+ // 0|0|0|内网IP|内网IP
+ String[] locals = location.split("|");
+ // log.info("locals {}", location);
+ if (locals.length > 2) {
+ if (locals[2].equals("0")) {
+ return "Local" + randomId;
+ }
+ return locals[2] + randomId;
+ }
+
+ return "Visitor";
+ }
+
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/message/Message.java b/modules/core/src/main/java/com/bytedesk/core/message/Message.java
index 81b45ded11..2c4e123170 100644
--- a/modules/core/src/main/java/com/bytedesk/core/message/Message.java
+++ b/modules/core/src/main/java/com/bytedesk/core/message/Message.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-29 16:21:24
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-15 09:18:02
+ * @LastEditTime: 2024-06-07 14:48:34
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -22,6 +22,8 @@ import org.hibernate.type.SqlTypes;
import com.bytedesk.core.base.BaseEntity;
import com.bytedesk.core.constant.BdConstants;
+import com.bytedesk.core.constant.TypeConsts;
+import com.bytedesk.core.enums.ClientEnum;
import com.bytedesk.core.thread.Thread;
import com.fasterxml.jackson.annotation.JsonIgnore;
@@ -45,25 +47,27 @@ public class Message extends BaseEntity {
private static final long serialVersionUID = 1L;
- // @NotBlank
- // @Column(unique = true, nullable = false)
- // private String mid;
+ @Builder.Default
+ // 尽管注释掉此行,在数据库中使用int类型存储,但前端查询的时候还是显示为字符串类型
+ // @Enumerated(EnumType.STRING) // 默认使用int类型表示,如果为了可读性,可以转换为使用字符串存储
+ @Column(name = TypeConsts.COLUMN_NAME_TYPE)
+ // private String type;
+ private MessageTypeEnum type = MessageTypeEnum.TEXT;
- @Column(name = "by_type")
- private String type;
-
- @Column(columnDefinition = "LONGTEXT")
+ // 复杂类型可以使用json存储在此,通过type字段区分
+ @Column(columnDefinition = TypeConsts.COLUMN_TYPE_TEXT)
private String content;
// @Builder.Default
- // @Column(columnDefinition = "json")
+ // @Column(columnDefinition = TypeConsts.COLUMN_TYPE_JSON)
// @JdbcTypeCode(SqlTypes.JSON)
// private String extra = BdConstants.EMPTY_JSON_STRING;
- /** send/stored/read */
- private String status;
+ @Builder.Default
+ private MessageStatusEnum status = MessageStatusEnum.SENT;
- private String client;
+ // private String client;
+ private ClientEnum client;
/** message belongs to */
@JsonIgnore
@@ -81,7 +85,7 @@ public class Message extends BaseEntity {
//
// h2 db 不能使用 user, 所以重定义为 by_user
@Builder.Default
- @Column(name = "by_user", columnDefinition = "json")
+ @Column(name = "by_user", columnDefinition = TypeConsts.COLUMN_TYPE_JSON)
@JdbcTypeCode(SqlTypes.JSON)
private String user = BdConstants.EMPTY_JSON_STRING;
diff --git a/modules/core/src/main/java/com/bytedesk/core/event/MessageBytesEvent.java b/modules/core/src/main/java/com/bytedesk/core/message/MessageBytesEvent.java
similarity index 97%
rename from modules/core/src/main/java/com/bytedesk/core/event/MessageBytesEvent.java
rename to modules/core/src/main/java/com/bytedesk/core/message/MessageBytesEvent.java
index e771dfd8c1..8e2845ca4f 100644
--- a/modules/core/src/main/java/com/bytedesk/core/event/MessageBytesEvent.java
+++ b/modules/core/src/main/java/com/bytedesk/core/message/MessageBytesEvent.java
@@ -12,7 +12,7 @@
* 联系:270580156@qq.com
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
*/
-package com.bytedesk.core.event;
+package com.bytedesk.core.message;
import org.springframework.context.ApplicationEvent;
diff --git a/modules/core/src/main/java/com/bytedesk/core/message/MessageController.java b/modules/core/src/main/java/com/bytedesk/core/message/MessageController.java
index bfd7723900..373494823d 100644
--- a/modules/core/src/main/java/com/bytedesk/core/message/MessageController.java
+++ b/modules/core/src/main/java/com/bytedesk/core/message/MessageController.java
@@ -66,4 +66,8 @@ public class MessageController {
}
+
+
+
+
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/event/MessageJsonEvent.java b/modules/core/src/main/java/com/bytedesk/core/message/MessageJsonEvent.java
similarity index 97%
rename from modules/core/src/main/java/com/bytedesk/core/event/MessageJsonEvent.java
rename to modules/core/src/main/java/com/bytedesk/core/message/MessageJsonEvent.java
index d57656184c..d8d8cf1814 100644
--- a/modules/core/src/main/java/com/bytedesk/core/event/MessageJsonEvent.java
+++ b/modules/core/src/main/java/com/bytedesk/core/message/MessageJsonEvent.java
@@ -12,7 +12,7 @@
* 联系:270580156@qq.com
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
*/
-package com.bytedesk.core.event;
+package com.bytedesk.core.message;
import org.springframework.context.ApplicationEvent;
diff --git a/modules/core/src/main/java/com/bytedesk/core/message/MessageNotify.java b/modules/core/src/main/java/com/bytedesk/core/message/MessageNotify.java
new file mode 100644
index 0000000000..79ebe8ce7c
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/message/MessageNotify.java
@@ -0,0 +1,62 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-02-21 10:00:55
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-05 22:34:42
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.message;
+
+import java.util.Date;
+
+import com.bytedesk.core.base.BaseResponse;
+import com.bytedesk.core.rbac.user.UserResponseSimple;
+import com.bytedesk.core.thread.ThreadResponseSimpleWithoutExtra;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+/**
+ * response for visitor init/request thread
+ * distinguish visitor message from agent view
+ * 区分 访客端拉取的消息格式 和 客服端拉取到的消息格式
+ */
+@Data
+@Builder
+@Accessors(chain = true)
+@AllArgsConstructor
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class MessageNotify extends BaseResponse {
+
+ private static final long serialVersionUID = 1L;
+
+ // private String type;
+ private MessageTypeEnum type;
+
+ private String content;
+
+ private String status;
+
+ private String client;
+
+ private Date createdAt;
+
+ /** */
+ private ThreadResponseSimpleWithoutExtra thread;
+
+ /** */
+ private UserResponseSimple user;
+
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/message/MessageRepository.java b/modules/core/src/main/java/com/bytedesk/core/message/MessageRepository.java
index 916542eeaf..a810d710a1 100644
--- a/modules/core/src/main/java/com/bytedesk/core/message/MessageRepository.java
+++ b/modules/core/src/main/java/com/bytedesk/core/message/MessageRepository.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-29 16:21:24
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-14 15:24:43
+ * @LastEditTime: 2024-06-05 22:59:59
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -23,7 +23,7 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;
import io.swagger.v3.oas.annotations.tags.Tag;
-import jakarta.transaction.Transactional;
+// import jakarta.transaction.Transactional;
/**
* QuerydslPredicateExecutor
@@ -34,8 +34,8 @@ public interface MessageRepository extends JpaRepository, JpaSpec
Optional findByUid(String uid);
- @Transactional
- Long deleteByUid(String uid);
+ // @Transactional
+ // Long deleteByUid(String uid);
Page findByThreadsUidIn(String[] threadTids, Pageable pageable);
@@ -43,6 +43,6 @@ public interface MessageRepository extends JpaRepository, JpaSpec
boolean existsByUid(String uid);
- Page findByOrgUid(String orgUid, Pageable pageable);
+ // Page findByOrgUidAndDeleted(String orgUid, Boolean deleted, Pageable pageable);
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/message/MessageResponse.java b/modules/core/src/main/java/com/bytedesk/core/message/MessageResponse.java
index b7588c3668..30d23e1b56 100644
--- a/modules/core/src/main/java/com/bytedesk/core/message/MessageResponse.java
+++ b/modules/core/src/main/java/com/bytedesk/core/message/MessageResponse.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-02-21 10:00:55
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-04 10:48:05
+ * @LastEditTime: 2024-06-06 10:37:11
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -17,6 +17,7 @@ package com.bytedesk.core.message;
import java.util.Date;
import com.bytedesk.core.base.BaseResponse;
+import com.bytedesk.core.enums.ClientEnum;
import com.bytedesk.core.rbac.user.UserResponseSimple;
import com.bytedesk.core.thread.ThreadResponseSimple;
@@ -40,25 +41,23 @@ import lombok.experimental.Accessors;
@EqualsAndHashCode(callSuper = true)
public class MessageResponse extends BaseResponse {
- private static final long serialVersionUID = 9911390153L;
+ private static final long serialVersionUID = 1L;
- /** message */
- // private String mid;
-
- private String type;
+ // private String type;
+ private MessageTypeEnum type;
private String content;
- private String status;
+ // private String status;
+ private MessageStatusEnum status;
- private String client;
+ // private String client;
+ private ClientEnum client;
private Date createdAt;
- /** */
private ThreadResponseSimple thread;
- /** */
private UserResponseSimple user;
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/message/MessageService.java b/modules/core/src/main/java/com/bytedesk/core/message/MessageService.java
index 7319f438b0..9e115e48b9 100644
--- a/modules/core/src/main/java/com/bytedesk/core/message/MessageService.java
+++ b/modules/core/src/main/java/com/bytedesk/core/message/MessageService.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-29 16:21:24
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-10 22:13:38
+ * @LastEditTime: 2024-05-24 15:45:13
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -25,10 +25,11 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
+import org.springframework.data.jpa.domain.Specification;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
-import com.bytedesk.core.utils.BdConvertUtils;
+import com.bytedesk.core.utils.ConvertUtils;
import lombok.AllArgsConstructor;
@@ -39,16 +40,17 @@ public class MessageService {
private final MessageRepository messageRepository;
-
public Page queryAll(MessageRequest request) {
// 优先加载最新聊天记录,也即:id越大越新
Pageable pageable = PageRequest.of(request.getPageNumber(), request.getPageSize(), Sort.Direction.DESC,
"createdAt");
-
- Page messagePage = messageRepository.findByOrgUid(request.getOrgUid(), pageable);
- return messagePage.map(BdConvertUtils::convertToMessageResponse);
+ Specification specs = MessageSpecs.search(request);
+ Page messagePage = messageRepository.findAll(specs, pageable);
+ // Page messagePage = messageRepository.findByOrgUidAndDeleted(request.getOrgUid(), false, pageable);
+
+ return messagePage.map(ConvertUtils::convertToMessageResponse);
}
public Page query(MessageRequest request) {
@@ -59,7 +61,7 @@ public class MessageService {
Page messagePage = messageRepository.findByThreadsUidIn(request.getThreads(), pageable);
- return messagePage.map(BdConvertUtils::convertToMessageResponse);
+ return messagePage.map(ConvertUtils::convertToMessageResponse);
}
@Cacheable(value = "message", key = "#uid", unless = "#result == null")
@@ -87,14 +89,19 @@ public class MessageService {
@CacheEvict(value = "message", key = "#message.uid"),
})
public void delete(@NonNull Message message) {
- messageRepository.delete(message);
+ deleteByUid(message.getUid());
}
@Caching(evict = {
@CacheEvict(value = "message", key = "#uid"),
})
public void deleteByUid(String uid) {
- messageRepository.deleteByUid(uid);
+ // messageRepository.deleteByUid(uid);
+ Optional messageOptional = findByUid(uid);
+ messageOptional.ifPresent(message -> {
+ message.setDeleted(true);
+ save(message);
+ });
}
public boolean existsByUid(String uid) {
diff --git a/modules/core/src/main/java/com/bytedesk/core/message/MessageSpecs.java b/modules/core/src/main/java/com/bytedesk/core/message/MessageSpecs.java
new file mode 100644
index 0000000000..184ad29190
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/message/MessageSpecs.java
@@ -0,0 +1,51 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-06-05 22:53:57
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-06 08:58:36
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.message;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.util.StringUtils;
+
+import com.bytedesk.core.base.BaseSpecification;
+
+import jakarta.persistence.criteria.Predicate;
+
+public class MessageSpecs extends BaseSpecification {
+
+ public static Specification search(MessageRequest request) {
+ return (root, query, criteriaBuilder) -> {
+ List predicates = new ArrayList<>();
+ predicates.addAll(getBasicPredicates(root, criteriaBuilder, request.getOrgUid()));
+ //
+ if (StringUtils.hasText(request.getContent())) {
+ predicates.add(criteriaBuilder.like(root.get("content"), "%" + request.getContent() + "%"));
+ }
+ //
+ // if (StringUtils.hasText(request.getType())) {
+ // predicates.add(criteriaBuilder.equal(root.get("type"), "%" +
+ // request.getType() + "%"));
+ // }
+ //
+ if (StringUtils.hasText(request.getClient())) {
+ predicates.add(criteriaBuilder.like(root.get("client"), "%" + request.getClient() + "%"));
+ }
+ //
+ return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
+ };
+ }
+
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/message/MessageStatusEnum.java b/modules/core/src/main/java/com/bytedesk/core/message/MessageStatusEnum.java
new file mode 100644
index 0000000000..e2661b9338
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/message/MessageStatusEnum.java
@@ -0,0 +1,26 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-05-25 10:33:49
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-04 11:19:54
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.message;
+
+public enum MessageStatusEnum {
+ PENDING, // 发送中
+ ERROR, // 发送失败
+ SENT, // 发送成功
+ RECALL, // 撤回
+ DELIVERED, // 已送达
+ READ, // 已读
+ DESTROYED, // 已销毁
+ LEAVE_MSG, // 离线留言
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/message/MessageTypeConsts.java b/modules/core/src/main/java/com/bytedesk/core/message/MessageTypeConsts.java
deleted file mode 100644
index 2b6966ebc2..0000000000
--- a/modules/core/src/main/java/com/bytedesk/core/message/MessageTypeConsts.java
+++ /dev/null
@@ -1,597 +0,0 @@
-/*
- * @Author: jackning 270580156@qq.com
- * @Date: 2024-02-22 15:51:39
- * @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-10 14:47:45
- * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
- * Please be aware of the BSL license restrictions before installing Bytedesk IM –
- * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
- * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
- * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
- * contact: 270580156@qq.com
- * 联系:270580156@qq.com
- * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
- */
-package com.bytedesk.core.message;
-
-public class MessageTypeConsts {
-
- private MessageTypeConsts() {
- }
-
- /**
- * 消息类型:文本
- */
- public static final String TEXT = "text";
- /**
- * 图片消息
- */
- public static final String IMAGE = "image";
- /**
- * 文件类型
- */
- public static final String FILE = "file";
- /**
- * 录音消息
- */
- public static final String VOICE = "voice";
- /**
- * 短视频
- */
- public static final String VIDEO = "video";
- /**
- * 选择消息类型
- */
- public static final String CHOICE = "choice";
- /**
- * 表单问卷消息类型
- */
- public static final String SURVEY = "survey";
- /**
- * 音乐
- */
- public static final String MUSIC = "music";
- /**
- *
- */
- public static final String SHORT_VIDEO = "shortvideo";
- /**
- *
- */
- public static final String LOCATION = "location";
- /**
- * 卡片消息
- */
- public static final String CARD = "card";
- /**
- * 视频号商品消息
- */
- public static final String CHANNELS_SHOP_PRODUCT = "channels_shop_product";
- /**
- * 视频号订单消息
- */
- public static final String CHANNELS_SHOP_ORDER = "channels_shop_order";
- /**
- * 图文链接
- * https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/kf-mgnt/kf-message/sendCustomMessage.html
- */
- public static final String LINK = "link";
- /**
- * 小程序卡片
- * https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/kf-mgnt/kf-message/sendCustomMessage.html
- */
- public static final String MINIPROGRAMPAGE = "miniprogrampage";
- /**
- * 菜单消息 https://kf.weixin.qq.com/api/doc/path/94744
- */
- public static final String MSGMENU = "msgmenu";
- public static final String CLICK = "click";
- public static final String MINIPROGRAM = "miniprogram";
- /**
- * 名片消息
- * https://kf.weixin.qq.com/api/doc/path/94744
- */
- public static final String BUSINESS_CARD = "business_card";
- /**
- *
- */
- public static final String EVENT = "event";
- /**
- * https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/subscribe-message.html
- * 1、当用户触发订阅消息弹框后,用户的相关行为事件结果会推送至开发者所配置的服务器地址或微信云托管服务。
- */
- public static final String SUBSCRIBE_MSG_POP_EVENT = "subscribe_msg_popup_event";
- /**
- * https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/subscribe-message.html
- * 2、当用户在手机端服务通知里消息卡片右上角“...”管理消息时,相应的行为事件会推送至开发者所配置的服务器地址或微信云托管服务。(目前只推送取消订阅的事件,即对消息设置“拒收”)
- */
- public static final String SUBSCRIBE_MSG_CHANGE_EVENT = "subscribe_msg_change_event";
- /**
- * https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/subscribe-message.html
- * 3、调用订阅消息接口发送消息给用户的最终结果,会推送下发结果事件至开发者所配置的服务器地址或微信云托管服务。
- */
- public static final String SUBSCRIBE_MSG_SENT_EVENT = "subscribe_msg_sent_event";
-
- /**
- * 自定义消息类型:内容放在content字段
- */
- public static final String CUSTOM = "custom";
- /**
- * 红包
- */
- public static final String RED_PACKET = "red_packet";
- /**
- * 商品
- */
- public static final String COMMODITY = "commodity";
- /**
- * subscribe(订阅)
- * TODO: 用户未关注时,进行关注后的事件推送
- */
- public static final String MESSAGE_EVENT_TYPE_SUBSCRIBE = "subscribe";
- /**
- * unsubscribe(取消订阅)
- */
- public static final String MESSAGE_EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";
- /**
- * 事件类型 annual_renew,提醒公众号需要去年审了
- */
- public static final String MESSAGE_EVENT_TYPE_ANNUAL_RENEW = "annual_renew";
- // 资质认证成功(此时立即获得接口权限)
- public static final String MESSAGE_EVENT_TYPE_QUALIFICATION_SUCCESS = "qualification_verify_success";
- // 资质认证失败
- public static final String MESSAGE_EVENT_TYPE_QUALIFICATION_FAILED = "qualification_verify_fail";
- // 名称认证成功(即命名成功)
- public static final String MESSAGE_EVENT_TYPE_NAMING_SUCCESS = "naming_verify_success";
- // 名称认证失败
- public static final String MESSAGE_EVENT_TYPE_NAMING_FAILED = "naming_verify_fail";
- // 消息发送失败事件
- public static final String MESSAGE_EVENT_TYPE_MSG_SEND_FAILED = "msg_send_fail";
- // 用户撤回消息事件
- public static final String MESSAGE_EVENT_TYPE_USER_RECALL_MSG = "user_recall_msg";
- /**
- * 用户已关注时的事件推送
- */
- public static final String MESSAGE_EVENT_TYPE_SCAN = "SCAN";
- /**
- * 上报地理位置事件
- */
- public static final String MESSAGE_EVENT_TYPE_LOCATION = "LOCATION";
- /**
- * 点击菜单跳转链接时的事件推送
- */
- public static final String MESSAGE_EVENT_TYPE_MENU_VIEW = "VIEW";
- /**
- * 自定义菜单事件
- */
- public static final String MESSAGE_EVENT_TYPE_MENU_CLICK = "CLICK";
- /**
- * 群发消息推送结果
- */
- public static final String MESSAGE_EVENT_TYPE_MASSSENDJOBFINISH = "MASSSENDJOBFINISH";
- /**
- * 模板消息推送结果
- */
- public static final String MESSAGE_EVENT_TYPE_TEMPLATESENDJOBFINISH = "TEMPLATESENDJOBFINISH";
- /**
- * 点击自定义菜单请求客服
- */
- public static final String MESSAGE_EVENT_KEY_MENU_CLICK_AGENT = "event_agent";
- /**
- * 点击自定义菜单请求'关于我们'
- */
- public static final String MESSAGE_EVENT_KEY_MENU_CLICK_ABOUT = "event_about";
- /**
- * 自定义菜单事件推送: 扫码推事件的事件推送
- */
- public static final String MESSAGE_EVENT_TYPE_MENU_SCANCODE_PUSH = "scancode_push";
- /**
- * 自定义菜单事件推送: 扫码推事件且弹出“消息接收中”提示框的事件推送
- */
- public static final String MESSAGE_EVENT_TYPE_MENU_SCANCODE_WAITMSG = "scancode_waitmsg";
- /**
- * 自定义菜单事件推送: 弹出系统拍照发图的事件推送
- */
- public static final String MESSAGE_EVENT_TYPE_MENU_PIC_SYSPHOTO = "pic_sysphoto";
- /**
- * 自定义菜单事件推送: 弹出拍照或者相册发图的事件推送
- */
- public static final String MESSAGE_EVENT_TYPE_MENU_PIC_PHOTO_OR_ALBUM = "pic_photo_or_album";
- /**
- * 自定义菜单事件推送: 弹出微信相册发图器的事件推送
- */
- public static final String MESSAGE_EVENT_TYPE_MENU_PIC_WEIXIN = "pic_weixin";
- /**
- * 自定义菜单事件推送: 弹出地理位置选择器的事件推送
- */
- public static final String MESSAGE_EVENT_TYPE_MENU_LOCATION_SELECT = "location_select";
- /**
- * 自定义菜单事件推送: 点击菜单跳转小程序的事件推送
- */
- public static final String MESSAGE_EVENT_TYPE_MENU_VIEW_MINIPROGRAM = "view_miniprogram";
- /**
- * 机器人, 自动回复
- */
- public static final String ROBOT = "robot";
-
- public static final String ROBOT_V2 = "robotv2";
-
- public static final String ROBOT_WELCOME = "robot_welcome";
- /**
- * 问卷
- */
- public static final String QUESTIONNAIRE = "questionnaire";
- /**
- * 分公司,方便提取分公司所包含的国家,金吉列大学长
- */
- public static final String COMPANY = "company";
- /**
- * 选择工作组
- */
- public static final String WORK_GROUP = "workgroup";
- /**
- *
- */
- public static final String NOTIFICATION = "notification";
- /**
- * 非工作时间
- */
- public static final String NOTIFICATION_NON_WORKING_TIME = "notification_non_working_time";
- /**
- * 客服离线,当前无客服在线
- */
- public static final String NOTIFICATION_OFFLINE = "notification_offline";
- /**
- * 开始浏览页面
- */
- public static final String NOTIFICATION_BROWSE_START = "notification_browse_start";
- /**
- * 浏览页面结束
- */
- public static final String NOTIFICATION_BROWSE_END = "notification_browse_end";
- /**
- * 邀请访客
- */
- public static final String NOTIFICATION_BROWSE_INVITE = "notification_browse_invite";
- /**
- * 访客接受邀请
- */
- public static final String NOTIFICATION_BROWSE_INVITE_ACCEPT = "notification_browse_invite_accept";
- /**
- * 访客拒绝邀请
- */
- public static final String NOTIFICATION_BROWSE_INVITE_REJECT = "notification_browse_invite_reject";
- /**
- * 新进入会话
- */
- public static final String NOTIFICATION_THREAD = "notification_thread";
- /**
- * 重新进入会话
- */
- public static final String NOTIFICATION_THREAD_REENTRY = "notification_thread_reentry";
- /**
- * 新建工单
- */
- public static final String NOTIFICATION_TICKET = "notification_ticket";
- /**
- * 意见反馈
- */
- public static final String NOTIFICATION_FEEDBACK = "notification_feedback";
- /**
- * 留言
- */
- public static final String NOTIFICATION_LEAVEMESSAGE = "notification_leavemessage";
- /**
- * 新进入队列
- */
- public static final String NOTIFICATION_QUEUE = "notification_queue";
- /**
- * 排队中离开
- */
- public static final String NOTIFICATION_QUEUE_LEAVE = "notification_queue_leave";
- /**
- * 接入队列访客
- */
- public static final String NOTIFICATION_QUEUE_ACCEPT = "notification_queue_accept";
- /**
- * 忽略队列访客
- */
- public static final String NOTIFICATION_QUEUE_IGNORE = "notification_queue_ignore";
- /**
- * 超时队列访客
- */
- public static final String NOTIFICATION_QUEUE_TIMEOUT = "notification_queue_timeout";
- /**
- * 自动接入会话
- */
- public static final String NOTIFICATION_ACCEPT_AUTO = "notification_accept_auto";
- /**
- * 手动接入
- */
- public static final String NOTIFICATION_ACCEPT_MANUAL = "notification_accept_manual";
- /**
- * 上线
- */
- public static final String NOTIFICATION_CONNECT = "notification_connect";
- /**
- * 离线
- */
- public static final String NOTIFICATION_DISCONNECT = "notification_disconnect";
- /**
- * 离开会话页面
- */
- public static final String NOTIFICATION_LEAVE = "notification_leave";
- /**
- * 客服关闭会话
- */
- public static final String NOTIFICATION_AGENT_CLOSE = "notification_agent_close";
- /**
- * 访客关闭会话
- */
- public static final String NOTIFICATION_VISITOR_CLOSE = "notification_visitor_close";
- /**
- * 自动关闭会话
- */
- public static final String NOTIFICATION_AUTO_CLOSE = "notification_auto_close";
- /**
- * 邀请会话
- */
- public static final String NOTIFICATION_INVITE = "notification_invite";
- /**
- * 接受邀请
- */
- public static final String NOTIFICATION_INVITE_ACCEPT = "notification_invite_accept";
- /**
- * 拒绝邀请
- */
- public static final String NOTIFICATION_INVITE_REJECT = "notification_invite_reject";
- /**
- * 转接会话
- */
- public static final String NOTIFICATION_TRANSFER = "notification_transfer";
- /**
- * 接受转接
- */
- public static final String NOTIFICATION_TRANSFER_ACCEPT = "notification_transfer_accept";
- /**
- * 拒绝转接
- */
- public static final String NOTIFICATION_TRANSFER_REJECT = "notification_transfer_reject";
- /**
- * 满意度请求
- */
- // public static final String NOTIFICATION_RATE_REQUEST =
- // "notification_rate_request";
- /**
- * 评价
- */
- // public static final String NOTIFICATION_RATE =
- // "notification_rate";
- /**
- * 人工客服邀请评价
- */
- public static final String NOTIFICATION_INVITE_RATE = "notification_invite_rate";
- /**
- * 评价人工客服结果
- */
- public static final String NOTIFICATION_RATE_RESULT = "notification_rate_result";
- /**
- * 评价机器人答案:有帮助
- */
- public static final String NOTIFICATION_RATE_HELPFUL = "notification_rate_helpful";
- /**
- * 评价机器人答案:无帮助
- */
- public static final String NOTIFICATION_RATE_HELPLESS = "notification_rate_helpless";
- /**
- * 通知支付结果
- */
- public static final String NOTIFICATION_PAY_RESULT = "notification_pay_result";
- /**
- * 普通用户设置 在线状态消息
- */
- public static final String NOTIFICATION_ONLINE_STATUS = "notification_online_status";
- /**
- * 长连接状态
- */
- public static final String NOTIFICATION_CONNECTION_STATUS = "notification_connection_status";
- /**
- * 客服设置接待状态
- */
- public static final String NOTIFICATION_ACCEPT_STATUS = "notification_accept_status";
- /**
- * 消息预知
- */
- public static final String NOTIFICATION_PREVIEW = "notification_preview";
- // 正在输入
- public static final String NOTIFICATION_TYPING = "notification_typing";
- /**
- * 消息撤回
- */
- public static final String NOTIFICATION_RECALL = "notification_recall";
- /**
- * 消息被拒绝
- */
- public static final String NOTIFICATION_BLOCK = "notification_block";
- /**
- * 访客浏览网页,通知客服端
- */
- public static final String NOTIFICATION_BROWSE = "notification_browse";
- /**
- * 非会话类消息通知
- */
- public static final String NOTIFICATION_NOTICE = "notification_notice";
- /**
- * 频道通知
- */
- public static final String NOTIFICATION_CHANNEL = "notification_channel";
- /**
- * 消息回执:收到消息之后回复给消息发送方
- * 消息content字段存放status: 1. MESSAGE_STATUS_RECEIVED(received), 2.
- * MESSAGE_STATUS_READ(read)
- */
- public static final String NOTIFICATION_RECEIPT = "notification_receipt";
- /**
- * 发送消息错误:推送给微信等第三方平台回执
- */
- public static final String NOTIFICATION_ERROR = "notification_error";
- /**
- * 踢掉其他客户端
- */
- public static final String NOTIFICATION_KICKOFF = "notification_kickoff";
- /**
- * 窗口抖动提醒
- */
- public static final String NOTIFICATION_SHAKE = "notification_shake";
- /**
- * 发送表单请求
- */
- public static final String NOTIFICATION_FORM = "notification_form";
-
- // 表单内嵌类型
- public static final String NOTIFICATION_FORM_REQUEST = "notification_form_request";
- public static final String NOTIFICATION_FORM_RESULT = "notification_form_result";
- /**
- * webrtc通知初始化localStream
- */
- public static final String NOTIFICATION_WEBRTC_INVITE_VIDEO = "notification_webrtc_invite_video";
- public static final String NOTIFICATION_WEBRTC_INVITE_AUDIO = "notification_webrtc_invite_audio";
- /**
- * webrtc取消邀请
- */
- public static final String NOTIFICATION_WEBRTC_CANCEL = "notification_webrtc_cancel";
- /**
- * webrtc邀请视频会话
- */
- public static final String NOTIFICATION_WEBRTC_OFFER_VIDEO = "notification_webrtc_offer_video";
- /**
- * webrtc邀请音频会话
- */
- public static final String NOTIFICATION_WEBRTC_OFFER_AUDIO = "notification_webrtc_offer_audio";
- /**
- * 接受webrtc邀请
- */
- public static final String NOTIFICATION_WEBRTC_ANSWER = "notification_webrtc_answer";
- /**
- * webrtc candidate信息
- */
- public static final String NOTIFICATION_WEBRTC_CANDIDATE = "notification_webrtc_candidate";
- /**
- * 接受webrtc邀请
- */
- public static final String NOTIFICATION_WEBRTC_ACCEPT = "notification_webrtc_accept";
- /**
- * 拒绝webrtc邀请
- */
- public static final String NOTIFICATION_WEBRTC_REJECT = "notification_webrtc_reject";
- /**
- * 被邀请方视频设备 + peeConnection已经就绪
- */
- public static final String NOTIFICATION_WEBRTC_READY = "notification_webrtc_ready";
- /**
- * webrtc忙线
- */
- public static final String NOTIFICATION_WEBRTC_BUSY = "notification_webrtc_busy";
- /**
- * 结束webrtc会话
- */
- public static final String NOTIFICATION_WEBRTC_CLOSE = "notification_webrtc_close";
- /**
- * 用户进入页面,来源于小程序
- */
- public static final String USER_ENTER_TEMPSESSION = "user_enter_tempsession";
- /**
- * 创建群组
- */
- public static final String NOTIFICATION_GROUP_CREATE = "notification_group_create";
- /**
- * 更新群名称、简介等
- */
- public static final String NOTIFICATION_GROUP_UPDATE = "notification_group_update";
- /**
- * 群公告
- */
- public static final String NOTIFICATION_GROUP_ANNOUNCEMENT = "notification_group_announcement";
- /**
- * 邀请多人加入群
- */
- public static final String NOTIFICATION_GROUP_INVITE = "notification_group_invite";
- /**
- * 受邀请:同意
- */
- public static final String NOTIFICATION_GROUP_INVITE_ACCEPT = "notification_group_invite_accept";
- /**
- * 受邀请:拒绝
- */
- public static final String NOTIFICATION_GROUP_INVITE_REJECT = "notification_group_invite_reject";
- /**
- * 不需要审核加入群组
- */
- public static final String NOTIFICATION_GROUP_JOIN = "notification_group_join";
- /**
- * 主动申请加入群组
- */
- public static final String NOTIFICATION_GROUP_APPLY = "notification_group_apply";
- /**
- * 同意:主动申请加群
- */
- public static final String NOTIFICATION_GROUP_APPLY_APPROVE = "notification_group_apply_approve";
- /**
- * 拒绝:主动申请加群
- */
- public static final String NOTIFICATION_GROUP_APPLY_DENY = "notification_group_apply_deny";
- /**
- * 踢人
- */
- public static final String NOTIFICATION_GROUP_KICK = "notification_group_kick";
- /**
- * 禁言
- */
- public static final String NOTIFICATION_GROUP_MUTE = "notification_group_mute";
- /**
- * 取消禁言
- */
- public static final String NOTIFICATION_GROUP_UNMUTE = "notification_group_unmute";
- /**
- * 设置管理员
- */
- public static final String NOTIFICATION_GROUP_SET_ADMIN = "notification_group_set_admin";
- /**
- * 取消设置管理员
- */
- public static final String NOTIFICATION_GROUP_UNSET_ADMIN = "notification_group_unset_admin";
- /**
- * 移交群组
- */
- public static final String NOTIFICATION_GROUP_TRANSFER = "notification_group_transfer";
- /**
- * 移交群组:同意、接受
- */
- public static final String NOTIFICATION_GROUP_TRANSFER_ACCEPT = "notification_group_transfer_accept";
- /**
- * 移交群组:拒绝
- */
- public static final String NOTIFICATION_GROUP_TRANSFER_REJECT = "notification_group_transfer_reject";
- /**
- * 退出群组
- */
- public static final String NOTIFICATION_GROUP_WITHDRAW = "notification_group_withdraw";
- /**
- * 解散群组
- */
- public static final String NOTIFICATION_GROUP_DISMISS = "notification_group_dismiss";
-
-
-
- /**
- * 回执
- */
- // 服务器回复客户端,已经收到。消息发送成功
- public static final String NOTIFICATION_ACK_SUCCESS = "notification_ack_success";
- // 消息送达
- public static final String NOTIFICATION_ACK_RECEIVED = "notification_ack_received";
- // 消息已读
- public static final String NOTIFICATION_ACK_READ = "notification_ack_read";
-
-}
diff --git a/modules/core/src/main/java/com/bytedesk/core/message/MessageTypeEnum.java b/modules/core/src/main/java/com/bytedesk/core/message/MessageTypeEnum.java
new file mode 100644
index 0000000000..c71219c2fb
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/message/MessageTypeEnum.java
@@ -0,0 +1,48 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-06-05 21:50:54
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-05 22:15:10
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.message;
+
+public enum MessageTypeEnum {
+ TEXT("text"), // 0.文本
+ IMAGE("image"), // 1.图片
+ FILE("file"), // 2.文件
+ VOICE("voice"), // 3.语音
+ VIDEO("video"), // 4.视频
+ THREAD("thread"), // 5.新会话
+ TYPING("typing"), // 6.正在输入
+ RECALL("recall"), // 7.撤回
+ RECEIPT("receipt"), // 8.消息回执
+ QA("qa"); // 问答
+
+ private final String value;
+
+ MessageTypeEnum(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ // 根据字符串查找对应的枚举常量
+ public static MessageTypeEnum fromValue(String value) {
+ for (MessageTypeEnum type : MessageTypeEnum.values()) {
+ if (type.getValue().equalsIgnoreCase(value)) {
+ return type;
+ }
+ }
+ throw new IllegalArgumentException("No MessageTypeEnum constant with value: " + value);
+ }
+}
\ No newline at end of file
diff --git a/modules/core/src/main/java/com/bytedesk/core/notice/Notice.java b/modules/core/src/main/java/com/bytedesk/core/notice/Notice.java
new file mode 100644
index 0000000000..1060806841
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/notice/Notice.java
@@ -0,0 +1,8 @@
+package com.bytedesk.core.notice;
+
+/**
+ * notice
+ */
+public class Notice {
+
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/push/Notifier.java b/modules/core/src/main/java/com/bytedesk/core/push/Notifier.java
index 147f40d7f7..f5b1a5c571 100644
--- a/modules/core/src/main/java/com/bytedesk/core/push/Notifier.java
+++ b/modules/core/src/main/java/com/bytedesk/core/push/Notifier.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-29 15:49:55
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-04-25 15:55:19
+ * @LastEditTime: 2024-06-01 16:14:54
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -16,7 +16,9 @@ package com.bytedesk.core.push;
import com.bytedesk.core.message.Message;
+import jakarta.servlet.http.HttpServletRequest;
+
public abstract class Notifier {
abstract void notify(Message e);
- abstract void send(String to, String content);
+ abstract void send(String to, String content, HttpServletRequest request);
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/push/Push.java b/modules/core/src/main/java/com/bytedesk/core/push/Push.java
index c86897cbbf..db1664dd4e 100644
--- a/modules/core/src/main/java/com/bytedesk/core/push/Push.java
+++ b/modules/core/src/main/java/com/bytedesk/core/push/Push.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-25 15:30:11
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-17 17:36:41
+ * @LastEditTime: 2024-05-29 12:07:27
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -16,7 +16,7 @@ package com.bytedesk.core.push;
import com.bytedesk.core.base.BaseEntity;
import com.bytedesk.core.constant.BdConstants;
-import com.bytedesk.core.constant.StatusConsts;
+import com.bytedesk.core.constant.TypeConsts;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
@@ -34,29 +34,35 @@ import lombok.experimental.Accessors;
@Data
@Entity
@Builder
-@EqualsAndHashCode(callSuper=false)
+@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "core_push")
public class Push extends BaseEntity {
-
+
private static final long serialVersionUID = 1L;
private String sender;
-
+
private String content;
private String receiver;
- @Column(name = "by_type")
+ @Column(name = TypeConsts.COLUMN_NAME_TYPE)
private String type;
-
+
+ private String ip;
+
+ // according to ip address
+ private String ipLocation;
+
@Builder.Default
- private String status = StatusConsts.CODE_STATUS_PENDING;
-
+ // private String status = StatusConsts.CODE_STATUS_PENDING;
+ private PushStatus status = PushStatus.PENDING;
+
private String client;
@Builder.Default
- private String platform = BdConstants.PLATFORM_BYTEDESK;
+ private String platform = BdConstants.PLATFORM_BYTEDESK;
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/push/PushRepository.java b/modules/core/src/main/java/com/bytedesk/core/push/PushRepository.java
index 3a1ab9aac3..15851b36ca 100644
--- a/modules/core/src/main/java/com/bytedesk/core/push/PushRepository.java
+++ b/modules/core/src/main/java/com/bytedesk/core/push/PushRepository.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-25 15:42:24
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-13 12:57:07
+ * @LastEditTime: 2024-05-25 10:49:27
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -21,11 +21,11 @@ import org.springframework.data.jpa.repository.JpaRepository;
public interface PushRepository extends JpaRepository {
- List findByStatus(String status);
+ List findByStatus(PushStatus status);
- Optional findByStatusAndTypeAndReceiverAndContent(String status, String type, String receiver, String content);
+ Optional findByStatusAndTypeAndReceiverAndContent(PushStatus status, String type, String receiver, String content);
- Boolean existsByStatusAndTypeAndReceiver(String status, String type, String receiver);
+ Boolean existsByStatusAndTypeAndReceiver(PushStatus status, String type, String receiver);
- Boolean existsByStatusAndTypeAndReceiverAndContent(String status, String type, String receiver, String content);
+ Boolean existsByStatusAndTypeAndReceiverAndContent(PushStatus status, String type, String receiver, String content);
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/push/PushRequest.java b/modules/core/src/main/java/com/bytedesk/core/push/PushRequest.java
index 4bf709ee16..9dcbf1957a 100644
--- a/modules/core/src/main/java/com/bytedesk/core/push/PushRequest.java
+++ b/modules/core/src/main/java/com/bytedesk/core/push/PushRequest.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-25 15:42:01
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-17 17:36:51
+ * @LastEditTime: 2024-05-29 12:07:41
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -16,7 +16,6 @@ package com.bytedesk.core.push;
import com.bytedesk.core.base.BaseRequest;
import com.bytedesk.core.constant.BdConstants;
-import com.bytedesk.core.constant.StatusConsts;
import lombok.AllArgsConstructor;
import lombok.Builder;
@@ -42,8 +41,14 @@ public class PushRequest extends BaseRequest {
private String receiver;
+ private String ip;
+
+ // according to ip address
+ private String ipLocation;
+
@Builder.Default
- private String status = StatusConsts.CODE_STATUS_PENDING;
+ // private String status = StatusConsts.CODE_STATUS_PENDING;
+ private PushStatus status = PushStatus.PENDING;
@Builder.Default
private String platform = BdConstants.PLATFORM_BYTEDESK;
diff --git a/modules/core/src/main/java/com/bytedesk/core/push/PushService.java b/modules/core/src/main/java/com/bytedesk/core/push/PushService.java
index ec149403cc..5c5afe9dae 100644
--- a/modules/core/src/main/java/com/bytedesk/core/push/PushService.java
+++ b/modules/core/src/main/java/com/bytedesk/core/push/PushService.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-25 15:41:33
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-13 12:57:27
+ * @LastEditTime: 2024-06-01 16:15:31
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -26,14 +26,16 @@ import org.springframework.cache.annotation.Caching;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
-import com.bytedesk.core.constant.StatusConsts;
+import com.bytedesk.core.config.BytedeskProperties;
import com.bytedesk.core.constant.TypeConsts;
import com.bytedesk.core.exception.EmailExistsException;
import com.bytedesk.core.exception.MobileExistsException;
+import com.bytedesk.core.ip.IpService;
import com.bytedesk.core.rbac.user.UserService;
import com.bytedesk.core.uid.UidUtils;
import com.bytedesk.core.utils.Utils;
+import jakarta.servlet.http.HttpServletRequest;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -54,17 +56,23 @@ public class PushService {
private final UserService userService;
- public Boolean sendEmailCode(String email, String client, String authType, String platform) {
+ private final BytedeskProperties bytedeskProperties;
- return sendCode(email, TypeConsts.TYPE_EMAIL, client, authType, platform);
+ private final IpService ipService;
+
+ public Boolean sendEmailCode(String email, String client, String authType, String platform,
+ HttpServletRequest request) {
+
+ return sendCode(email, TypeConsts.TYPE_EMAIL, client, authType, platform, request);
}
- public Boolean sendSmsCode(String mobile, String client, String authType, String platform) {
+ public Boolean sendSmsCode(String mobile, String client, String authType, String platform, HttpServletRequest request) {
- return sendCode(mobile, TypeConsts.TYPE_MOBILE, client, authType, platform);
+ return sendCode(mobile, TypeConsts.TYPE_MOBILE, client, authType, platform, request);
}
- public Boolean sendCode(String receiver, String type, String client, String authType, String platform) {
+ public Boolean sendCode(String receiver, String type, String client, String authType, String platform,
+ HttpServletRequest request) {
// 注册验证码,如果账号已经存在,则直接抛出异常
if (authType.equals(TypeConsts.SEND_MOBILE_CODE_TYPE_REGISTER)) {
@@ -79,20 +87,28 @@ public class PushService {
}
// check if has already send validate code within 15min
- if (existsByStatusAndTypeAndReceiver(StatusConsts.CODE_STATUS_PENDING, type, receiver)) {
+ if (existsByStatusAndTypeAndReceiver(PushStatus.PENDING, type, receiver)) {
return false;
}
- String code = Utils.getRandomCode(receiver);
+ String code = "";
+ if (Utils.isTestMobile(receiver) || Utils.isTestEmail(receiver) || bytedeskProperties.isInWhitelist(receiver)) {
+ code = bytedeskProperties.getMobileCode();
+ log.info("test code: {}", code);
+ } else {
+ code = Utils.getRandomCode(receiver);
+ }
if (type.equals(TypeConsts.TYPE_EMAIL)) {
- pushServiceImplEmail.send(receiver, code);
+ pushServiceImplEmail.send(receiver, code, request);
} else if (type.equals(TypeConsts.TYPE_MOBILE)) {
- pushServiceImplSms.send(receiver, code);
+ pushServiceImplSms.send(receiver, code, request);
} else {
return false;
}
+ String ip = ipService.getIp(request);
+ String ipLocation = ipService.getIpLocation(ip);
//
PushRequest pushRequest = new PushRequest();
pushRequest.setType(type);
@@ -101,6 +117,8 @@ public class PushService {
pushRequest.setReceiver(receiver);
pushRequest.setClient(client);
pushRequest.setPlatform(platform);
+ pushRequest.setIp(ip);
+ pushRequest.setIpLocation(ipLocation);
create(pushRequest);
return true;
@@ -134,9 +152,10 @@ public class PushService {
// }
// return result;
//
- Optional pushOptional = findByStatusAndTypeAndReceiverAndContent(StatusConsts.CODE_STATUS_PENDING, type, receiver, code);
+ Optional pushOptional = findByStatusAndTypeAndReceiverAndContent(PushStatus.PENDING, type, receiver, code);
if (pushOptional.isPresent()) {
- pushOptional.get().setStatus(StatusConsts.CODE_STATUS_CONFIRM);
+ // pushOptional.get().setStatus(StatusConsts.CODE_STATUS_CONFIRM);
+ pushOptional.get().setStatus(PushStatus.CONFIRMED);
save(pushOptional.get());
return true;
}
@@ -144,11 +163,11 @@ public class PushService {
}
// @Cacheable(value = "push", key = "#receiver-#status-#type", unless = "#result == null")
- public Optional findByStatusAndTypeAndReceiverAndContent(String status, String type, String receiver, String content) {
+ public Optional findByStatusAndTypeAndReceiverAndContent(PushStatus status, String type, String receiver, String content) {
return pushRepository.findByStatusAndTypeAndReceiverAndContent(status, type, receiver, content);
}
- public Boolean existsByStatusAndTypeAndReceiver(String status, String type, String receiver) {
+ public Boolean existsByStatusAndTypeAndReceiver(PushStatus status, String type, String receiver) {
return pushRepository.existsByStatusAndTypeAndReceiver(status, type, receiver);
}
@@ -163,7 +182,8 @@ public class PushService {
// TODO: 更新缓存
@Cacheable(value = "pushPending")
public List findStatusPending() {
- return pushRepository.findByStatus(StatusConsts.CODE_STATUS_PENDING);
+ // return pushRepository.findByStatus(StatusConsts.CODE_STATUS_PENDING);
+ return pushRepository.findByStatus(PushStatus.PENDING);
}
// 自动过期
@@ -179,7 +199,8 @@ public class PushService {
// 验证码有效时间15分钟
if (diffInMinutes > 15) {
// TODO: 过期,清空缓存
- push.setStatus(StatusConsts.CODE_STATUS_EXPIRED);
+ // push.setStatus(StatusConsts.CODE_STATUS_EXPIRED);
+ push.setStatus(PushStatus.EXPIRED);
save(push);
}
});
diff --git a/modules/core/src/main/java/com/bytedesk/core/push/PushServiceImplAndroid.java b/modules/core/src/main/java/com/bytedesk/core/push/PushServiceImplAndroid.java
index 96622596a6..7e750c6c33 100644
--- a/modules/core/src/main/java/com/bytedesk/core/push/PushServiceImplAndroid.java
+++ b/modules/core/src/main/java/com/bytedesk/core/push/PushServiceImplAndroid.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-31 15:30:30
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-04-26 12:55:50
+ * @LastEditTime: 2024-06-01 16:15:01
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -19,6 +19,8 @@ import org.springframework.stereotype.Service;
import com.bytedesk.core.message.Message;
+import jakarta.servlet.http.HttpServletRequest;
+
@Service
public class PushServiceImplAndroid extends Notifier {
@@ -31,7 +33,11 @@ public class PushServiceImplAndroid extends Notifier {
}
@Override
- void send(String to, String content) {
+ void send(String to, String content, HttpServletRequest request) {
+
+ // TODO: 检测同一个ip是否短时间内有发送过验证码,如果短时间内发送过,则不发送
+
+
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'send'");
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/push/PushServiceImplEmail.java b/modules/core/src/main/java/com/bytedesk/core/push/PushServiceImplEmail.java
index 6ad52139da..04ba8df4b1 100644
--- a/modules/core/src/main/java/com/bytedesk/core/push/PushServiceImplEmail.java
+++ b/modules/core/src/main/java/com/bytedesk/core/push/PushServiceImplEmail.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-31 15:30:19
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-15 12:38:02
+ * @LastEditTime: 2024-06-01 16:15:05
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -28,6 +28,7 @@ import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.bytedesk.core.message.Message;
+import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
/**
@@ -48,7 +49,7 @@ public class PushServiceImplEmail extends Notifier {
@Async
@Override
- void send(String email, String content) {
+ void send(String email, String content, HttpServletRequest request) {
log.info("send email to {}, content {}", email, content);
//
sendValidateCode(email, content);
@@ -77,6 +78,9 @@ public class PushServiceImplEmail extends Notifier {
return;
}
+ // TODO: 检测同一个ip是否短时间内有发送过验证码,如果短时间内发送过,则不发送
+
+
// 如果是除杭州region外的其它region(如新加坡、澳洲Region),需要将下面的"cn-hangzhou"替换为"ap-southeast-1"、或"ap-southeast-2"。
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
// 如果是除杭州region外的其它region(如新加坡region), 需要做如下处理
diff --git a/modules/core/src/main/java/com/bytedesk/core/push/PushServiceImplIos.java b/modules/core/src/main/java/com/bytedesk/core/push/PushServiceImplIos.java
index 60126d0824..446d0f7969 100644
--- a/modules/core/src/main/java/com/bytedesk/core/push/PushServiceImplIos.java
+++ b/modules/core/src/main/java/com/bytedesk/core/push/PushServiceImplIos.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-31 15:30:08
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-04-26 12:55:38
+ * @LastEditTime: 2024-05-29 12:10:15
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -19,6 +19,8 @@ import org.springframework.stereotype.Service;
import com.bytedesk.core.message.Message;
+import jakarta.servlet.http.HttpServletRequest;
+
@Service
public class PushServiceImplIos extends Notifier {
@@ -30,7 +32,10 @@ public class PushServiceImplIos extends Notifier {
}
@Override
- void send(String to, String content) {
+ void send(String to, String content, HttpServletRequest request) {
+
+ // TODO: 检测同一个ip是否短时间内有发送过验证码,如果短时间内发送过,则不发送
+
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'send'");
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/push/PushServiceImplSms.java b/modules/core/src/main/java/com/bytedesk/core/push/PushServiceImplSms.java
index a80cc4fc34..b54f83ee30 100644
--- a/modules/core/src/main/java/com/bytedesk/core/push/PushServiceImplSms.java
+++ b/modules/core/src/main/java/com/bytedesk/core/push/PushServiceImplSms.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-31 15:29:55
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-15 12:37:24
+ * @LastEditTime: 2024-06-01 16:15:15
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -28,6 +28,7 @@ import com.aliyuncs.profile.DefaultProfile;
import com.bytedesk.core.message.Message;
import com.bytedesk.core.utils.Utils;
+import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@@ -43,13 +44,20 @@ public class PushServiceImplSms extends Notifier {
@Async
@Override
- void send(String mobile, String content) {
+ void send(String mobile, String content, HttpServletRequest request) {
log.info("send sms to {}, content: {}", mobile, content);
+
+ // TODO: 检测同一个ip是否短时间内有发送过验证码,如果短时间内发送过,则不发送
+
+
// not test mobile, send sms
if (!Utils.isTestMobile(mobile)) {
sendValidateCode(mobile, content);
}
}
+
+ // @Value("${bytedesk.debug}")
+ // private Boolean debug;
@Value("${aliyun.access.key.id}")
private String accessKeyId;
@@ -65,6 +73,14 @@ public class PushServiceImplSms extends Notifier {
public void sendValidateCode(String phone, String code) {
+ // if (debug) {
+ // return;
+ // }
+
+
+
+
+
DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
IAcsClient client = new DefaultAcsClient(profile);
diff --git a/modules/core/src/main/java/com/bytedesk/core/push/PushStatus.java b/modules/core/src/main/java/com/bytedesk/core/push/PushStatus.java
new file mode 100644
index 0000000000..1170b324b9
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/push/PushStatus.java
@@ -0,0 +1,23 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-05-25 10:40:08
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-05-25 10:41:35
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.push;
+
+public enum PushStatus {
+ PENDING,
+ CONFIRMED,
+ EXPIRED,
+ SUCCESS,
+ FAILURE
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/quartz/QuartzController.java b/modules/core/src/main/java/com/bytedesk/core/quartz/QuartzController.java
index f74e8b138e..b45423b8bb 100644
--- a/modules/core/src/main/java/com/bytedesk/core/quartz/QuartzController.java
+++ b/modules/core/src/main/java/com/bytedesk/core/quartz/QuartzController.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-05-14 09:40:11
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-14 15:35:37
+ * @LastEditTime: 2024-05-31 07:40:32
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -45,7 +45,7 @@ public class QuartzController extends BaseController {
@Override
public ResponseEntity> queryByOrg(QuartzRequest request) {
- Page pageResult = this.quartzService.queryByOrg(request);
+ Page pageResult = quartzService.queryByOrg(request);
return ResponseEntity.ok(JsonResult.success(pageResult));
}
@@ -56,8 +56,8 @@ public class QuartzController extends BaseController {
@GetMapping("/query")
@Override
public ResponseEntity> query(QuartzRequest request) {
-
- Page pageResult = this.quartzService.queryByUser(request);
+
+ Page pageResult = quartzService.queryByUser(request);
return ResponseEntity.ok(JsonResult.success(pageResult));
}
@@ -65,20 +65,20 @@ public class QuartzController extends BaseController {
@PostMapping("/create")
@Override
public ResponseEntity> create(@RequestBody QuartzRequest request) {
-
- QuartzResponse response = this.quartzService.create(request);
+
+ QuartzResponse response = quartzService.create(request);
if (response == null) {
return ResponseEntity.badRequest().body(JsonResult.error("jobName already exists"));
}
-
+
return ResponseEntity.ok(JsonResult.success(response));
}
@PostMapping("/update")
@Override
public ResponseEntity> update(@RequestBody QuartzRequest request) {
-
- QuartzResponse response = this.quartzService.update(request);
+
+ QuartzResponse response = quartzService.update(request);
if (response == null) {
return ResponseEntity.badRequest().body(JsonResult.error("uid not exists"));
}
@@ -89,43 +89,35 @@ public class QuartzController extends BaseController {
@PostMapping("/delete")
@Override
public ResponseEntity> delete(@RequestBody QuartzRequest request) {
-
- this.quartzService.deleteByUid(request);
+
+ quartzService.deleteByUid(request.getUid());
return ResponseEntity.ok(JsonResult.success());
}
- @GetMapping("/filter")
- @Override
- public ResponseEntity> filter(QuartzRequest filterParam) {
- // TODO Auto-generated method stub
- throw new UnsupportedOperationException("Unimplemented method 'filter'");
- }
-
- //
+ //
@PostMapping("/startJob")
public ResponseEntity> startJob(@RequestBody QuartzRequest request) {
- this.quartzService.startJob(request);
+ quartzService.startJob(request);
return ResponseEntity.ok(JsonResult.success(request));
}
@PostMapping("/pauseJob")
public ResponseEntity> pauseJob(@RequestBody QuartzRequest request) {
- this.quartzService.pauseJob(request);
+ quartzService.pauseJob(request);
return ResponseEntity.ok(JsonResult.success(request));
}
@PostMapping("/resumeJob")
public ResponseEntity> resumeJob(@RequestBody QuartzRequest request) {
- this.quartzService.resumeJob(request);
+ quartzService.resumeJob(request);
return ResponseEntity.ok(JsonResult.success(request));
}
@PostMapping("/deleteJob")
public ResponseEntity> deleteJob(@RequestBody QuartzRequest request) {
- this.quartzService.deleteJob(request);
+ quartzService.deleteJob(request);
return ResponseEntity.ok(JsonResult.success(request));
}
-
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/event/QuartzFiveSecondEvent.java b/modules/core/src/main/java/com/bytedesk/core/quartz/QuartzFiveSecondEvent.java
similarity index 97%
rename from modules/core/src/main/java/com/bytedesk/core/event/QuartzFiveSecondEvent.java
rename to modules/core/src/main/java/com/bytedesk/core/quartz/QuartzFiveSecondEvent.java
index fb09e67abc..f2f8ff207e 100644
--- a/modules/core/src/main/java/com/bytedesk/core/event/QuartzFiveSecondEvent.java
+++ b/modules/core/src/main/java/com/bytedesk/core/quartz/QuartzFiveSecondEvent.java
@@ -12,7 +12,7 @@
* 联系:270580156@qq.com
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
*/
-package com.bytedesk.core.event;
+package com.bytedesk.core.quartz;
import org.springframework.context.ApplicationEvent;
diff --git a/modules/core/src/main/java/com/bytedesk/core/quartz/QuartzRepository.java b/modules/core/src/main/java/com/bytedesk/core/quartz/QuartzRepository.java
index 5d299358a8..6c3827d5ce 100644
--- a/modules/core/src/main/java/com/bytedesk/core/quartz/QuartzRepository.java
+++ b/modules/core/src/main/java/com/bytedesk/core/quartz/QuartzRepository.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-05-14 09:40:24
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-14 15:33:07
+ * @LastEditTime: 2024-05-24 15:46:40
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -20,7 +20,7 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
-import jakarta.transaction.Transactional;
+// import jakarta.transaction.Transactional;
public interface QuartzRepository extends JpaRepository {
@@ -28,10 +28,10 @@ public interface QuartzRepository extends JpaRepository {
Optional findByUid(String uid);
- Page findByOrgUid(String orgUid, Pageable pageable);
+ Page findByOrgUidAndDeleted(String orgUid, Boolean deleted, Pageable pageable);
Boolean existsByJobName(String jobName);
- @Transactional
- void deleteByUid(String uid);
+ // @Transactional
+ // void deleteByUid(String uid);
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/quartz/QuartzService.java b/modules/core/src/main/java/com/bytedesk/core/quartz/QuartzService.java
index e4ea355d46..919e19b046 100644
--- a/modules/core/src/main/java/com/bytedesk/core/quartz/QuartzService.java
+++ b/modules/core/src/main/java/com/bytedesk/core/quartz/QuartzService.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-05-14 09:39:46
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-15 14:19:28
+ * @LastEditTime: 2024-05-24 15:47:29
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -61,14 +61,12 @@ public class QuartzService extends BaseService queryByOrg(QuartzRequest request) {
Pageable pageable = PageRequest.of(request.getPageNumber(), request.getPageSize(), Sort.Direction.DESC, "updatedAt");
- Page page = quartzRepository.findByOrgUid(request.getOrgUid(), pageable);
+ Page page = quartzRepository.findByOrgUidAndDeleted(request.getOrgUid(), false, pageable);
return page.map(this::convertToResponse);
}
@@ -94,16 +92,16 @@ public class QuartzService extends BaseService {
+
+ private final QuickButtonService quickButtonService;
+
+ @GetMapping("/query/org")
+ @Override
+ public ResponseEntity> queryByOrg(QuickButtonRequest request) {
+
+ Page page = quickButtonService.queryByOrg(request);
+
+ return ResponseEntity.ok(JsonResult.success(page));
+ }
+
+ @Override
+ public ResponseEntity> query(QuickButtonRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'query'");
+ }
+
+ @PostMapping("/create")
+ @Override
+ public ResponseEntity> create(@RequestBody QuickButtonRequest request) {
+
+ QuickButtonResponse quickButton = quickButtonService.create(request);
+
+ return ResponseEntity.ok(JsonResult.success(quickButton));
+ }
+
+ @PostMapping("/update")
+ @Override
+ public ResponseEntity> update(@RequestBody QuickButtonRequest request) {
+
+ QuickButtonResponse quickButton = quickButtonService.update(request);
+
+ return ResponseEntity.ok(JsonResult.success(quickButton));
+ }
+
+ @PostMapping("/delete")
+ @Override
+ public ResponseEntity> delete(@RequestBody QuickButtonRequest request) {
+
+ quickButtonService.deleteByUid(request.getUid());
+
+ return ResponseEntity.ok(JsonResult.success(request.getUid()));
+ }
+
+
+
+}
diff --git a/modules/ai/src/main/java/com/bytedesk/ai/llm/LlmRepository.java b/modules/core/src/main/java/com/bytedesk/core/quick_button/QuickButtonRepository.java
similarity index 67%
rename from modules/ai/src/main/java/com/bytedesk/ai/llm/LlmRepository.java
rename to modules/core/src/main/java/com/bytedesk/core/quick_button/QuickButtonRepository.java
index faa3aec9a1..9a3876aad6 100644
--- a/modules/ai/src/main/java/com/bytedesk/ai/llm/LlmRepository.java
+++ b/modules/core/src/main/java/com/bytedesk/core/quick_button/QuickButtonRepository.java
@@ -1,8 +1,8 @@
/*
* @Author: jackning 270580156@qq.com
- * @Date: 2024-03-25 12:08:06
+ * @Date: 2024-03-22 23:02:37
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-03-25 15:29:44
+ * @LastEditTime: 2024-06-07 15:09:07
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -12,20 +12,14 @@
* 联系:270580156@qq.com
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
*/
-package com.bytedesk.ai.llm;
+package com.bytedesk.core.quick_button;
+
+import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
-import org.springframework.stereotype.Repository;
-import io.swagger.v3.oas.annotations.tags.Tag;
+public interface QuickButtonRepository extends JpaRepository, JpaSpecificationExecutor {
-/**
- * 大模型
- */
-@Repository
-@Tag(name = "Lllm info - 大模型")
-// @PreAuthorize("hasRole('ROLE_ADMIN')")
-public interface LlmRepository extends JpaRepository, JpaSpecificationExecutor{
-
+ Optional findByUid(String uid);
}
diff --git a/modules/team/src/main/java/com/bytedesk/team/organization/OrganizationRequest.java b/modules/core/src/main/java/com/bytedesk/core/quick_button/QuickButtonRequest.java
similarity index 69%
rename from modules/team/src/main/java/com/bytedesk/team/organization/OrganizationRequest.java
rename to modules/core/src/main/java/com/bytedesk/core/quick_button/QuickButtonRequest.java
index dc186b4d65..1780f48230 100644
--- a/modules/team/src/main/java/com/bytedesk/team/organization/OrganizationRequest.java
+++ b/modules/core/src/main/java/com/bytedesk/core/quick_button/QuickButtonRequest.java
@@ -1,8 +1,8 @@
/*
* @Author: jackning 270580156@qq.com
- * @Date: 2024-02-06 16:02:35
+ * @Date: 2024-03-22 23:02:47
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-04-23 14:13:05
+ * @LastEditTime: 2024-03-22 23:02:48
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -12,24 +12,26 @@
* 联系:270580156@qq.com
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
*/
-package com.bytedesk.team.organization;
+package com.bytedesk.core.quick_button;
import com.bytedesk.core.base.BaseRequest;
+import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
@Data
@EqualsAndHashCode(callSuper = false)
-public class OrganizationRequest extends BaseRequest {
+@AllArgsConstructor
+@NoArgsConstructor
+public class QuickButtonRequest extends BaseRequest {
- // private String oid;
+ private String title;
- private String name;
+ private String content;
- private String logo;
+ private String type;
- private String code;
-
- private String description;
+ private String orgUid;
}
diff --git a/modules/service/src/main/java/com/bytedesk/service/quick_button/QuickButtonResponse.java b/modules/core/src/main/java/com/bytedesk/core/quick_button/QuickButtonResponse.java
similarity index 57%
rename from modules/service/src/main/java/com/bytedesk/service/quick_button/QuickButtonResponse.java
rename to modules/core/src/main/java/com/bytedesk/core/quick_button/QuickButtonResponse.java
index cee51fe320..886e75fb8f 100644
--- a/modules/service/src/main/java/com/bytedesk/service/quick_button/QuickButtonResponse.java
+++ b/modules/core/src/main/java/com/bytedesk/core/quick_button/QuickButtonResponse.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-22 23:02:56
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-03-22 23:02:57
+ * @LastEditTime: 2024-06-08 12:07:27
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -12,8 +12,30 @@
* 联系:270580156@qq.com
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
*/
-package com.bytedesk.service.quick_button;
+package com.bytedesk.core.quick_button;
-public class QuickButtonResponse {
+import java.util.Date;
+import com.bytedesk.core.base.BaseResponse;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+@AllArgsConstructor
+@NoArgsConstructor
+public class QuickButtonResponse extends BaseResponse {
+
+ private String title;
+
+ private String content;
+
+ private String type;
+
+ private String orgUid;
+
+ private Date updatedAt;
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/quick_button/QuickButtonService.java b/modules/core/src/main/java/com/bytedesk/core/quick_button/QuickButtonService.java
new file mode 100644
index 0000000000..15d673990d
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/quick_button/QuickButtonService.java
@@ -0,0 +1,131 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-03-22 23:02:24
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-08 12:10:12
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.quick_button;
+
+import java.util.Optional;
+
+import org.modelmapper.ModelMapper;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.orm.ObjectOptimisticLockingFailureException;
+import org.springframework.stereotype.Service;
+
+import com.bytedesk.core.base.BaseService;
+import com.bytedesk.core.uid.UidUtils;
+
+import lombok.AllArgsConstructor;
+
+@Service
+@AllArgsConstructor
+public class QuickButtonService extends BaseService {
+
+ private final QuickButtonRepository quickButtonRepository;
+
+ private final ModelMapper modelMapper;
+
+ private final UidUtils uidUtils;
+
+ @Override
+ public Page queryByOrg(QuickButtonRequest request) {
+
+ Pageable pageable = PageRequest.of(request.getPageNumber(), request.getPageSize(), Sort.Direction.ASC,
+ "id");
+
+ Specification spec = QuickButtonSpecification.search(request);
+
+ Page quickButtonPage = quickButtonRepository.findAll(spec, pageable);
+
+ return quickButtonPage.map(this::convertToResponse);
+ }
+
+ @Override
+ public Page queryByUser(QuickButtonRequest request) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'queryByUser'");
+ }
+
+ @Override
+ public Optional findByUid(String uid) {
+ return quickButtonRepository.findByUid(uid);
+ }
+
+ @Override
+ public QuickButtonResponse create(QuickButtonRequest request) {
+
+ QuickButton quickButton = modelMapper.map(request, QuickButton.class);
+
+ quickButton.setUid(uidUtils.getCacheSerialUid());
+
+ return convertToResponse(save(quickButton));
+ }
+
+ @Override
+ public QuickButtonResponse update(QuickButtonRequest request) {
+
+ Optional quickButton = findByUid(request.getUid());
+ if (!quickButton.isPresent()) {
+ throw new RuntimeException("quickButton not found");
+ }
+ QuickButton entity = quickButton.get();
+ // modelMapper.map(request, entity);
+ //
+ entity.setTitle(request.getTitle());
+ entity.setContent(request.getContent());
+ entity.setType(request.getType());
+
+ entity.setOrgUid(request.getOrgUid());
+
+ return convertToResponse(save(entity));
+ }
+
+ @Override
+ public QuickButton save(QuickButton entity) {
+ try {
+ return quickButtonRepository.save(entity);
+ } catch (ObjectOptimisticLockingFailureException e) {
+ handleOptimisticLockingFailureException(e, entity);
+ }
+ return null;
+ }
+
+ @Override
+ public void deleteByUid(String uid) {
+ Optional quickButton = findByUid(uid);
+ if (quickButton.isPresent()) {
+ quickButton.get().setDeleted(true);
+ save(quickButton.get());
+ }
+ }
+
+ @Override
+ public void delete(QuickButton entity) {
+ quickButtonRepository.delete(entity);
+ }
+
+ @Override
+ public void handleOptimisticLockingFailureException(ObjectOptimisticLockingFailureException e, QuickButton entity) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'handleOptimisticLockingFailureException'");
+ }
+
+ @Override
+ public QuickButtonResponse convertToResponse(QuickButton entity) {
+ return modelMapper.map(entity, QuickButtonResponse.class);
+ }
+
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/quick_button/QuickButtonSpecification.java b/modules/core/src/main/java/com/bytedesk/core/quick_button/QuickButtonSpecification.java
new file mode 100644
index 0000000000..378f0ba0ca
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/quick_button/QuickButtonSpecification.java
@@ -0,0 +1,47 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-06-07 15:04:33
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-08 12:24:57
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.quick_button;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.util.StringUtils;
+
+import com.bytedesk.core.base.BaseSpecification;
+
+import jakarta.persistence.criteria.Predicate;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class QuickButtonSpecification extends BaseSpecification {
+
+ public static Specification search(QuickButtonRequest request) {
+ log.info("request: {}", request);
+ return (root, query, criteriaBuilder) -> {
+ List predicates = new ArrayList<>();
+ predicates.addAll(getBasicPredicates(root, criteriaBuilder, request.getOrgUid()));
+ //
+ if (StringUtils.hasText(request.getTitle())) {
+ predicates.add(criteriaBuilder.like(root.get("title"), "%" + request.getTitle() + "%"));
+ }
+ if (StringUtils.hasText(request.getContent())) {
+ predicates.add(criteriaBuilder.like(root.get("content"), "%" + request.getContent() + "%"));
+ }
+ //
+ return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
+ };
+ }
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthController.java b/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthController.java
index 16951aa38e..164e696e84 100644
--- a/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthController.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthController.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-29 16:21:24
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-17 17:24:47
+ * @LastEditTime: 2024-06-03 14:56:02
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -23,13 +23,14 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-import com.bytedesk.core.action.ActionLogAnnotation;
+import com.bytedesk.core.action.ActionAnnotation;
import com.bytedesk.core.push.PushService;
import com.bytedesk.core.rbac.user.UserRequest;
import com.bytedesk.core.rbac.user.UserResponse;
import com.bytedesk.core.rbac.user.UserService;
import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletRequest;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -72,8 +73,8 @@ public class AuthController {
return ResponseEntity.ok(JsonResult.success("register success", userResponse));
}
- @ActionLogAnnotation(title = "Auth", action = "loginWithUsernamePassword", description = "Login With Username & Password")
@PostMapping("/login")
+ @ActionAnnotation(title = "auth", action = "loginWithUsernamePassword", description = "Login With Username & Password")
public ResponseEntity> loginWithUsernamePassword(@RequestBody AuthRequest authRequest) {
log.debug("login {}", authRequest.toString());
@@ -86,11 +87,11 @@ public class AuthController {
}
@PostMapping("/send/mobile")
- public ResponseEntity> sendMobileCode(@RequestBody AuthRequest authRequest) {
+ public ResponseEntity> sendMobileCode(@RequestBody AuthRequest authRequest, HttpServletRequest request) {
log.debug("send mobile code {}, client {}, type {}", authRequest.toString(), authRequest.getClient(), authRequest.getType());
// send mobile code
- Boolean result = pushService.sendSmsCode(authRequest.getMobile(), authRequest.getClient(), authRequest.getType(), authRequest.getPlatform());
+ Boolean result = pushService.sendSmsCode(authRequest.getMobile(), authRequest.getClient(), authRequest.getType(), authRequest.getPlatform(), request);
if (!result) {
return ResponseEntity.ok().body(JsonResult.error("already send, dont repeat", -1, false));
}
@@ -98,7 +99,7 @@ public class AuthController {
return ResponseEntity.ok().body(JsonResult.success("send mobile code success"));
}
- @ActionLogAnnotation(title = "Auth", action = "loginWithMobileCode", description = "Login With mobile & code")
+ @ActionAnnotation(title = "auth", action = "loginWithMobileCode", description = "Login With mobile & code")
@PostMapping("/login/mobile")
public ResponseEntity> loginWithMobileCode(@RequestBody AuthRequest authRequest) {
log.debug("login mobile {}", authRequest.toString());
@@ -106,7 +107,7 @@ public class AuthController {
// validate mobile & code
// 验证手机验证码
if (!pushService.validateSmsCode(authRequest.getMobile(), authRequest.getCode())) {
- return ResponseEntity.ok().body(JsonResult.error("validate code failed", -1, new AuthResponse()));
+ return ResponseEntity.ok().body(JsonResult.error("validate code failed", -1, false));
}
// if mobile already exists, if none, then registe
@@ -127,11 +128,11 @@ public class AuthController {
}
@PostMapping("/send/email")
- public ResponseEntity> sendEmailCode(@RequestBody AuthRequest authRequest) {
+ public ResponseEntity> sendEmailCode(@RequestBody AuthRequest authRequest, HttpServletRequest request) {
log.debug("send email code {}", authRequest.toString());
// send email code
- Boolean result = pushService.sendEmailCode(authRequest.getEmail(), authRequest.getClient(), authRequest.getType(), authRequest.getPlatform());
+ Boolean result = pushService.sendEmailCode(authRequest.getEmail(), authRequest.getClient(), authRequest.getType(), authRequest.getPlatform(), request);
if (!result) {
return ResponseEntity.ok(JsonResult.error("already send, dont repeat", -1, false));
}
@@ -139,14 +140,14 @@ public class AuthController {
return ResponseEntity.ok(JsonResult.success("send email code success"));
}
- @ActionLogAnnotation(title = "Auth", action = "loginWithEmailCode", description = "Login With email & code")
+ @ActionAnnotation(title = "auth", action = "loginWithEmailCode", description = "Login With email & code")
@PostMapping("/login/email")
public ResponseEntity> loginWithEmailCode(@RequestBody AuthRequest authRequest) {
log.debug("login email {}", authRequest.toString());
// validate email & code
if (!pushService.validateEmailCode(authRequest.getEmail(), authRequest.getCode())) {
- return ResponseEntity.ok(JsonResult.error("validate code failed", -1, new AuthResponse()));
+ return ResponseEntity.ok(JsonResult.error("validate code failed", -1, false));
}
// 邮箱是否已经注册,如果没有,则自动注册
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthRequest.java b/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthRequest.java
index 35f676b885..ff2bd41369 100644
--- a/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthRequest.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthRequest.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-23 07:53:01
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-13 11:02:22
+ * @LastEditTime: 2024-06-03 16:21:08
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -16,6 +16,7 @@ package com.bytedesk.core.rbac.auth;
import com.bytedesk.core.base.BaseRequest;
+import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -38,6 +39,7 @@ public class AuthRequest extends BaseRequest {
private String code;
//
+ @NotBlank
private String platform;
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthService.java b/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthService.java
index 369302a09a..e5a7a1119c 100644
--- a/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthService.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthService.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-23 07:53:01
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-13 14:23:21
+ * @LastEditTime: 2024-06-03 14:55:52
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -27,6 +27,7 @@ import com.bytedesk.core.rbac.user.User;
import com.bytedesk.core.rbac.user.UserDetailsImpl;
import com.bytedesk.core.rbac.user.UserDetailsServiceImpl;
import com.bytedesk.core.rbac.user.UserResponse;
+import com.bytedesk.core.utils.ConvertUtils;
import com.bytedesk.core.utils.JwtUtils;
import jakarta.servlet.http.HttpServletRequest;
@@ -48,10 +49,27 @@ public class AuthService {
private ModelMapper modelMapper;
public User getCurrentUser() {
- UserDetailsImpl userDetails = (UserDetailsImpl) SecurityContextHolder.getContext().getAuthentication()
- .getPrincipal();
+ // not logged in
+ if (SecurityContextHolder.getContext().getAuthentication() == null) {
+ return null;
+ }
+ //
+ try {
+ UserDetailsImpl userDetails = (UserDetailsImpl) SecurityContextHolder.getContext().getAuthentication()
+ .getPrincipal();
- return modelMapper.map(userDetails, User.class);
+ return modelMapper.map(userDetails, User.class);
+ } catch (Exception e) {
+ // TODO: handle exception
+ // FIXME: 验证码错误时会报错:java.lang.ClassCastException: class java.lang.String cannot be cast to
+ // class com.bytedesk.core.rbac.user.UserDetailsImpl (java.lang.String is in
+ // module java.base of loader 'bootstrap';
+ // com.bytedesk.core.rbac.user.UserDetailsImpl is in unnamed module of loader
+ // 'app')
+ e.printStackTrace();
+ }
+
+ return null;
}
public UsernamePasswordAuthenticationToken getAuthentication(@NonNull HttpServletRequest request, String subject) {
@@ -83,7 +101,7 @@ public class AuthService {
UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
- UserResponse userResponse = convertToUserResponse(userDetails);
+ UserResponse userResponse = ConvertUtils.convertToUserResponse(userDetails);
String jwt = jwtUtils.generateJwtToken(userDetails.getUsername(), userDetails.getPlatform());
@@ -92,13 +110,5 @@ public class AuthService {
.user(userResponse)
.build();
}
-
- public UserResponse convertToUserResponse(UserDetailsImpl userDetails) {
- UserResponse userResponse = modelMapper.map(userDetails, UserResponse.class);
-
- return userResponse;
- }
-
-
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthJwtTokenFilter.java b/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthTokenFilter.java
similarity index 77%
rename from modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthJwtTokenFilter.java
rename to modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthTokenFilter.java
index c9f67ec450..255aae39f6 100644
--- a/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthJwtTokenFilter.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthTokenFilter.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-29 16:17:36
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-13 13:43:50
+ * @LastEditTime: 2024-05-23 20:49:57
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -34,7 +34,7 @@ import com.bytedesk.core.utils.JwtUtils;
@Slf4j
@Component
-public class AuthJwtTokenFilter extends OncePerRequestFilter {
+public class AuthTokenFilter extends OncePerRequestFilter {
@Autowired
private JwtUtils jwtUtils;
@@ -48,13 +48,11 @@ public class AuthJwtTokenFilter extends OncePerRequestFilter {
@NonNull FilterChain filterChain)
throws ServletException, IOException {
try {
- String jwt = parseJwt(request);
- log.debug("access_token {}", jwt);
- if (jwt != null && jwtUtils.validateJwtToken(jwt)) {
- String subject = jwtUtils.getSubjectFromJwtToken(jwt);
- // String username = jwtUtils.getUsernameFromJwtToken(jwt);
- // String platform = jwtUtils.getPlatformFromJwtToken(jwt);
- log.debug("subject {}", subject);
+ String accessToken = parseAccessToken(request);
+ // log.debug("accessToken {}", accessToken);
+ if (accessToken != null && jwtUtils.validateJwtToken(accessToken)) {
+ String subject = jwtUtils.getSubjectFromJwtToken(accessToken);
+ // log.debug("subject {}", subject);
//
UsernamePasswordAuthenticationToken authentication = authService.getAuthentication(request, subject);
SecurityContextHolder.getContext().setAuthentication(authentication);
@@ -65,13 +63,21 @@ public class AuthJwtTokenFilter extends OncePerRequestFilter {
filterChain.doFilter(request, response);
}
- private String parseJwt(HttpServletRequest request) {
+ private String parseAccessToken(HttpServletRequest request) {
String headerAuth = request.getHeader("Authorization");
+ // read header
if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) {
return headerAuth.substring(7);
}
+ // read parameter
+ headerAuth = request.getParameter("accessToken");
+ if (StringUtils.hasText(headerAuth)) {
+ // log.info("accessToken from request param: {}", headerAuth);
+ return headerAuth;
+ }
+
return null;
}
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/authority/Authority.java b/modules/core/src/main/java/com/bytedesk/core/rbac/authority/Authority.java
index 427a592ba8..88dd619357 100755
--- a/modules/core/src/main/java/com/bytedesk/core/rbac/authority/Authority.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/authority/Authority.java
@@ -22,6 +22,7 @@ import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import com.bytedesk.core.base.BaseEntity;
+import com.bytedesk.core.constant.TypeConsts;
import jakarta.persistence.*;
@@ -31,7 +32,7 @@ import jakarta.persistence.*;
@Data
@Builder
@Accessors(chain = true)
-@EqualsAndHashCode(callSuper=false)
+@EqualsAndHashCode(callSuper = false)
@Entity
@AllArgsConstructor
@NoArgsConstructor
@@ -50,7 +51,7 @@ public class Authority extends BaseEntity {
private String description;
- @Column(name = "by_type")
+ @Column(name = TypeConsts.COLUMN_NAME_TYPE)
private String type;
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/authority/AuthorityService.java b/modules/core/src/main/java/com/bytedesk/core/rbac/authority/AuthorityService.java
index 2507d7f0be..144d392696 100644
--- a/modules/core/src/main/java/com/bytedesk/core/rbac/authority/AuthorityService.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/authority/AuthorityService.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-29 16:21:24
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-04 10:39:41
+ * @LastEditTime: 2024-06-11 17:47:53
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -36,16 +36,16 @@ public class AuthorityService {
private final UidUtils uidUtils;
public Authority create(AuthorityRequest authorityRequest) {
- //
+ //
Authority authority = modelMapper.map(authorityRequest, Authority.class);
authority.setUid(uidUtils.getCacheSerialUid());
return save(authority);
}
- @Cacheable(value = "authority", key = "#aid", unless = "#result == null")
- public Optional findByAid(String aid) {
- return authorityRepository.findByUid(aid);
+ @Cacheable(value = "authority", key = "#uid", unless = "#result == null")
+ public Optional findByUid(String uid) {
+ return authorityRepository.findByUid(uid);
}
@Cacheable(value = "authority", key = "#value", unless = "#result == null")
@@ -62,27 +62,27 @@ public class AuthorityService {
if (authorityRepository.count() > 0) {
return;
}
- //
+ //
String[] authorities = {
- TypeConsts.AUTHORITY_SUPER,
- TypeConsts.AUTHORITY_ADMIN,
- TypeConsts.AUTHORITY_HR,
- TypeConsts.AUTHORITY_ORG,
- TypeConsts.AUTHORITY_IT,
- TypeConsts.AUTHORITY_MONEY,
- TypeConsts.AUTHORITY_MARKETING,
- TypeConsts.AUTHORITY_SALES,
- TypeConsts.AUTHORITY_CUSTOMER_SERVICE,
+ TypeConsts.SUPER,
+ TypeConsts.ADMIN,
+ TypeConsts.HR,
+ TypeConsts.ORG,
+ TypeConsts.IT,
+ TypeConsts.MONEY,
+ TypeConsts.MARKETING,
+ TypeConsts.SALES,
+ TypeConsts.CUSTOMER_SERVICE,
};
for (String authority : authorities) {
AuthorityRequest authRequest = AuthorityRequest.builder()
- .name(authority)
- .value(authority)
- .description(authority)
- .build();
+ .name(authority)
+ .value(authority)
+ .description(authority)
+ .build();
authRequest.setType(TypeConsts.TYPE_SYSTEM);
- //
+ //
create(authRequest);
}
diff --git a/modules/team/src/main/java/com/bytedesk/team/organization/Organization.java b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/Organization.java
similarity index 53%
rename from modules/team/src/main/java/com/bytedesk/team/organization/Organization.java
rename to modules/core/src/main/java/com/bytedesk/core/rbac/organization/Organization.java
index 7654cfeb84..5bf35fd858 100644
--- a/modules/team/src/main/java/com/bytedesk/team/organization/Organization.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/Organization.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-29 16:20:17
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-03 23:48:54
+ * @LastEditTime: 2024-06-11 16:56:56
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -12,10 +12,13 @@
* 联系:270580156@qq.com
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
*/
-package com.bytedesk.team.organization;
+package com.bytedesk.core.rbac.organization;
+
+import java.util.Date;
import com.bytedesk.core.base.BaseEntity;
import com.bytedesk.core.constant.AvatarConsts;
+import com.bytedesk.core.constant.I18Consts;
import com.bytedesk.core.rbac.user.User;
import com.fasterxml.jackson.annotation.JsonIgnore;
@@ -32,18 +35,15 @@ import lombok.experimental.Accessors;
@Data
@Builder
@Accessors(chain = true)
-@EqualsAndHashCode(callSuper = false)
+@EqualsAndHashCode(callSuper = false, exclude = {"user"})
@AllArgsConstructor
@NoArgsConstructor
-@Table(name = "team_organization")
+@EntityListeners({ OrganizationListener.class })
+@Table(name = "core_organization")
public class Organization extends BaseEntity {
private static final long serialVersionUID = 1L;
- // 随机字符串,可读性差
- // @Column(unique = true, nullable = false)
- // private String oid;
-
@NotBlank
/** name should be unique */
@Column(unique = true, nullable = false)
@@ -57,14 +57,60 @@ public class Organization extends BaseEntity {
@Column(unique = true)
private String code;
- private String description;
+ @Builder.Default
+ private String description = I18Consts.I18N_DESCRIPTION;
+ @Builder.Default
+ private boolean forceValidateEmail = false;
+
+ @Builder.Default
+ private boolean forceValidateMobile = false;
+
+ // @JsonIgnore
// @Builder.Default
// @OneToMany(fetch = FetchType.LAZY)
// private Set departments = new HashSet<>();
+
+ // Identity Verification 实名认证
+
+ // 认证类型:企业认证、个人认证、政府事业单位认证
+ // private String verifiedType;
+ private OrganizationVerifyTypeEnum verifiedType;
+
+ // 证件类型:营业执照、身份证、护照、其他
+ // private String identityType;
+ private OrganizationIdentityTypeEnum identityType;
+
+ // 证件图片:营业执照、身份证、护照、其他
+ private String identityImage;
+
+ // 证件号码:企业信用代码、身份证号码
+ private String identityNumber;
+
+ // 认证时间
+ private Date verifyDate;
+
+ // 认证状态:未认证、已认证、审核中、审核失败
+ // private String verifyStatus;
+ private OrganizationVerifyStatusEnum verifyStatus;
+
+ // 认证失败原因
+ private String rejectReason;
+
+
@JsonIgnore
@ManyToOne(fetch = FetchType.LAZY)
private User user;
+ @Override
+ public String toString() {
+ return "Organization{" +
+ "id=" + super.getId() +
+ ", uid=" + super.getUid() +
+ ", name='" + name + '\'' +
+ ", logo=" + logo +
+ '}';
+ }
+
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationApply.java b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationApply.java
new file mode 100644
index 0000000000..089f1dfcfe
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationApply.java
@@ -0,0 +1,55 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-06-03 12:10:03
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-03 12:12:10
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.rbac.organization;
+
+import com.bytedesk.core.base.BaseEntity;
+import com.bytedesk.core.rbac.user.User;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+@Entity
+@Data
+@Builder
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false, exclude = { "user" })
+@AllArgsConstructor
+@NoArgsConstructor
+@Table(name = "core_organization_apply")
+public class OrganizationApply extends BaseEntity {
+
+
+ private String note;
+
+ // apply user
+ @JsonIgnore
+ @ManyToOne(fetch = FetchType.LAZY)
+ private User user;
+
+ // apply organization
+ @JsonIgnore
+ @ManyToOne(fetch = FetchType.LAZY)
+ private Organization organization;
+
+}
diff --git a/modules/team/src/main/java/com/bytedesk/team/organization/OrganizationController.java b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationController.java
similarity index 75%
rename from modules/team/src/main/java/com/bytedesk/team/organization/OrganizationController.java
rename to modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationController.java
index 07abd6349d..15dce848cf 100644
--- a/modules/team/src/main/java/com/bytedesk/team/organization/OrganizationController.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationController.java
@@ -12,7 +12,7 @@
* 联系:270580156@qq.com
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
*/
-package com.bytedesk.team.organization;
+package com.bytedesk.core.rbac.organization;
import java.util.Optional;
@@ -22,9 +22,11 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
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;
+import com.bytedesk.core.action.ActionAnnotation;
import com.bytedesk.core.utils.JsonResult;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -64,15 +66,28 @@ public class OrganizationController {
* @param request
* @return
*/
+ @ActionAnnotation(title = "organization", action = "create", description = "organization create")
@PostMapping("/create")
- public ResponseEntity> create(OrganizationRequest request) {
+ public ResponseEntity> create(@RequestBody OrganizationRequest request) {
//
- Organization org = organizationService.create(request);
+ OrganizationResponse org = organizationService.create(request);
if (org == null) {
return ResponseEntity.ok(JsonResult.error("创建组织失败"));
}
//
- return ResponseEntity.ok(JsonResult.success());
+ return ResponseEntity.ok(JsonResult.success(org));
+ }
+
+ @ActionAnnotation(title = "organization", action = "update", description = "organization update")
+ @PostMapping("/update")
+ public ResponseEntity> update(@RequestBody OrganizationRequest request) {
+ //
+ OrganizationResponse org = organizationService.update(request);
+ if (org == null) {
+ return ResponseEntity.ok(JsonResult.error("更新组织失败"));
+ }
+ //
+ return ResponseEntity.ok(JsonResult.success(org));
}
/**
@@ -88,7 +103,7 @@ public class OrganizationController {
return ResponseEntity.ok(JsonResult.error("组织不存在"));
}
//
- return ResponseEntity.ok(JsonResult.success(organizationService.convertToOrganizationResponse(org.get())));
+ return ResponseEntity.ok(JsonResult.success(organizationService.convertToResponse(org.get())));
}
/** user join organization by oid */
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationCreateEvent.java b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationCreateEvent.java
new file mode 100644
index 0000000000..c7ba146592
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationCreateEvent.java
@@ -0,0 +1,32 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-06-03 14:01:50
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-03 14:01:53
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.rbac.organization;
+
+import org.springframework.context.ApplicationEvent;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class OrganizationCreateEvent extends ApplicationEvent {
+
+ private static final long serialVersionUID = 1L;
+
+ public OrganizationCreateEvent(Organization organization) {
+ super(organization);
+ }
+
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationEventHandler.java b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationEventHandler.java
new file mode 100644
index 0000000000..ec1a4c70fc
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationEventHandler.java
@@ -0,0 +1,5 @@
+package com.bytedesk.core.rbac.organization;
+
+public class OrganizationEventHandler {
+
+}
diff --git a/modules/service/src/main/java/com/bytedesk/service/customer/CustomerNameOnly.java b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationIdentityTypeEnum.java
similarity index 70%
rename from modules/service/src/main/java/com/bytedesk/service/customer/CustomerNameOnly.java
rename to modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationIdentityTypeEnum.java
index 517d6d3fdf..b3552dc258 100644
--- a/modules/service/src/main/java/com/bytedesk/service/customer/CustomerNameOnly.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationIdentityTypeEnum.java
@@ -1,8 +1,8 @@
/*
* @Author: jackning 270580156@qq.com
- * @Date: 2024-04-12 12:55:55
+ * @Date: 2024-06-11 16:00:48
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-04-12 15:11:08
+ * @LastEditTime: 2024-06-11 16:00:50
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -12,14 +12,12 @@
* 联系:270580156@qq.com
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
*/
-package com.bytedesk.service.customer;
-
-/**
- * https://docs.spring.io/spring-data/jpa/reference/repositories/projections.html
- */
-public interface CustomerNameOnly {
-
- String getName();
- // Optional getName();
+package com.bytedesk.core.rbac.organization;
+public enum OrganizationIdentityTypeEnum {
+ COMPANY_LICENSE, // 公司营业执照
+ ID_CARD, // 身份证
+ PASSPORT, // 护照
+ DRIVER_LICENSE, // 驾驶证
+ OTHER // 其他
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationListener.java b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationListener.java
new file mode 100644
index 0000000000..b1666a2405
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationListener.java
@@ -0,0 +1,47 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-06-03 13:57:38
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-12 07:04:38
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.rbac.organization;
+
+import org.springframework.stereotype.Component;
+
+import com.bytedesk.core.constant.UserConsts;
+
+// import com.bytedesk.core.event.BytedeskEventPublisher;
+// import com.bytedesk.core.utils.ApplicationContextHolder;
+
+import jakarta.persistence.PostPersist;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@Component
+@AllArgsConstructor
+public class OrganizationListener {
+
+ // 这允许你执行一些后续操作,比如发布事件、更新缓存、触发其他业务逻辑等
+ @PostPersist
+ public void onPostCreate(Organization organization) {
+ log.info("onPostCreate: {}", organization);
+
+ if (UserConsts.DEFAULT_ORGANIZATION_UID.equals(organization.getUid())) {
+ return;
+ }
+
+ // 放在此处会报错,直接放到service Create中
+ // BytedeskEventPublisher bytedeskEventPublisher = ApplicationContextHolder.getBean(BytedeskEventPublisher.class);
+ // bytedeskEventPublisher.publishOrganizationCreateEvent(organization);
+ }
+
+}
diff --git a/modules/team/src/main/java/com/bytedesk/team/organization/OrganizationRepository.java b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationRepository.java
similarity index 81%
rename from modules/team/src/main/java/com/bytedesk/team/organization/OrganizationRepository.java
rename to modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationRepository.java
index 85053eda6b..4edb674ef4 100644
--- a/modules/team/src/main/java/com/bytedesk/team/organization/OrganizationRepository.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationRepository.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-29 16:20:17
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-04 11:25:54
+ * @LastEditTime: 2024-06-03 13:02:51
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -12,7 +12,7 @@
* 联系:270580156@qq.com
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
*/
-package com.bytedesk.team.organization;
+package com.bytedesk.core.rbac.organization;
import java.util.Optional;
@@ -22,7 +22,7 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
// import org.springframework.data.rest.core.annotation.RepositoryRestResource;
-import org.springframework.data.rest.core.annotation.RestResource;
+// import org.springframework.data.rest.core.annotation.RestResource;
import org.springframework.lang.NonNull;
// import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Repository;
@@ -49,9 +49,10 @@ public interface OrganizationRepository
Optional findByUid(String uid);
- //
- @RestResource(path = "name", rel = "name")
- Optional findFirstByName(String name);
+ // @RestResource(path = "name", rel = "name")
+ Optional findByNameAndDeleted(String name, Boolean deleted);
+
+ Optional findByCodeAndDeleted(String code, Boolean deleted);
//
// @NonNull
@@ -61,7 +62,11 @@ public interface OrganizationRepository
//
Page findByUser(User user, Pageable pageable);
- @RestResource(exported = false)
+ Boolean existsByNameAndDeleted(String name, Boolean deleted);
+
+ Boolean existsByCodeAndDeleted(String code, Boolean deleted);
+
+ // @RestResource(exported = false)
void deleteById(@NonNull Long id);
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationRequest.java b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationRequest.java
new file mode 100644
index 0000000000..d20c208101
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationRequest.java
@@ -0,0 +1,67 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-02-06 16:02:35
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-11 16:03:08
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.rbac.organization;
+
+import java.util.Date;
+
+import com.bytedesk.core.base.BaseRequest;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+@AllArgsConstructor
+@NoArgsConstructor
+public class OrganizationRequest extends BaseRequest {
+
+ private String name;
+
+ private String logo;
+
+ private String code;
+
+ private String description;
+
+
+ // Identity Verification 实名认证
+
+ // 认证类型:企业认证、个人认证、政府事业单位认证
+ // private String verifiedType;
+ private OrganizationVerifyTypeEnum verifiedType;
+
+ // 证件类型:营业执照、身份证、护照、其他
+ // private String identityType;
+ private OrganizationIdentityTypeEnum identityType;
+
+ // 证件图片:营业执照、身份证、护照、其他
+ private String identityImage;
+
+ // 证件号码:企业信用代码、身份证号码
+ private String identityNumber;
+
+ // 认证时间
+ private Date verifyDate;
+
+ // 认证状态:未认证、已认证、审核中、审核失败
+ // private String verifyStatus;
+ private OrganizationVerifyStatusEnum verifyStatus;
+
+ // 认证失败原因
+ private String rejectReason;
+
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationResponse.java b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationResponse.java
new file mode 100644
index 0000000000..dfad258835
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationResponse.java
@@ -0,0 +1,72 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-02-01 21:20:57
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-11 16:03:15
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.rbac.organization;
+
+import java.util.Date;
+
+import com.bytedesk.core.base.BaseResponse;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+@Data
+@Builder
+@Accessors(chain = true)
+@AllArgsConstructor
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class OrganizationResponse extends BaseResponse {
+
+ private static final long serialVersionUID = 1L;
+
+ private String name;
+
+ private String logo;
+
+ private String code;
+
+ private String description;
+
+
+ // Identity Verification 实名认证
+
+ // 认证类型:企业认证、个人认证、政府事业单位认证
+ // private String verifiedType;
+ private OrganizationVerifyTypeEnum verifiedType;
+
+ // 证件类型:营业执照、身份证、护照、其他
+ // private String identityType;
+ private OrganizationIdentityTypeEnum identityType;
+
+ // 证件图片:营业执照、身份证、护照、其他
+ private String identityImage;
+
+ // 证件号码:企业信用代码、身份证号码
+ private String identityNumber;
+
+ // 认证时间
+ private Date verifyDate;
+
+ // 认证状态:未认证、已认证、审核中、审核失败
+ // private String verifyStatus;
+ private OrganizationVerifyStatusEnum verifyStatus;
+
+ // 认证失败原因
+ private String rejectReason;
+
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationRestEventHandler.java b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationRestEventHandler.java
new file mode 100644
index 0000000000..71c9a72130
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationRestEventHandler.java
@@ -0,0 +1,83 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-02-01 09:22:48
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-11 17:09:56
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.rbac.organization;
+
+/**
+ * https://docs.spring.io/spring-data/rest/reference/events.html
+ */
+// @Slf4j
+// @Component
+// @AllArgsConstructor
+// @RepositoryEventHandler(Organization.class)
+// public class OrganizationRestEventHandler {
+
+// // private AuthService authService;
+
+// // private UserService userService;
+
+// @HandleBeforeCreate
+// public void beforeCreate(Organization organization) {
+// log.debug("beforeCreate");
+// // User user = authService.getCurrentUser();
+// // organization.setUid(Utils.getUid());
+// // organization.setUser(user);
+// // //
+// // user.getOrganizations().add(organization.getUid());
+// // userService.save(user);
+// }
+
+// @HandleAfterCreate
+// public void afterCreate(Organization organization) {
+// log.debug("afterCreate");
+
+// }
+
+// @HandleBeforeSave
+// public void beforeSave(Organization organization) {
+// log.debug("beforeSave");
+
+// }
+
+// @HandleAfterSave
+// public void afterSave(Organization organization) {
+// log.debug("afterSave");
+
+// }
+
+// @HandleBeforeLinkSave
+// public void beforeLinkSave(Organization organization) {
+// log.debug("beforeLinkSave");
+
+// }
+
+// @HandleAfterLinkSave
+// public void afterLinkSave(Organization organization) {
+// log.debug("afterLinkSave");
+
+// }
+
+// @HandleBeforeDelete
+// public void beforeDelete(Organization organization) {
+// log.debug("beforeDelete");
+
+// }
+
+// @HandleAfterDelete
+// public void afterDelete(Organization organization) {
+// log.debug("afterDelete");
+
+// }
+
+// }
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationService.java b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationService.java
new file mode 100644
index 0000000000..ff77038635
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationService.java
@@ -0,0 +1,225 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-01-29 16:20:17
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-12 09:55:01
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.rbac.organization;
+
+import java.util.Optional;
+
+import org.modelmapper.ModelMapper;
+import org.springframework.cache.annotation.CachePut;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.cache.annotation.Caching;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.orm.ObjectOptimisticLockingFailureException;
+import org.springframework.stereotype.Service;
+
+import com.bytedesk.core.config.BytedeskProperties;
+import com.bytedesk.core.constant.TypeConsts;
+import com.bytedesk.core.constant.UserConsts;
+import com.bytedesk.core.event.BytedeskEventPublisher;
+import com.bytedesk.core.rbac.auth.AuthService;
+import com.bytedesk.core.rbac.role.Role;
+import com.bytedesk.core.rbac.role.RoleService;
+import com.bytedesk.core.rbac.user.User;
+import com.bytedesk.core.rbac.user.UserService;
+import com.bytedesk.core.uid.UidUtils;
+
+import jakarta.transaction.Transactional;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@Service
+@AllArgsConstructor
+public class OrganizationService {
+
+ private final AuthService authService;
+
+ private final UserService userService;
+
+ private final RoleService roleService;
+
+ private final BytedeskProperties bytedeskProperties;
+
+ private final OrganizationRepository organizationRepository;
+
+ private final UidUtils uidUtils;
+
+ private final ModelMapper modelMapper;
+
+ private final BytedeskEventPublisher bytedeskEventPublisher;
+
+ public Page query(OrganizationRequest pageParam) {
+
+ User user = authService.getCurrentUser();
+
+ Pageable pageable = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize(), Sort.Direction.DESC,
+ "id");
+
+ Page orgPage = organizationRepository.findByUser(user, pageable);
+
+ return orgPage.map(organization -> convertToResponse(organization));
+ }
+
+ @Transactional
+ public OrganizationResponse create(OrganizationRequest organizationRequest) {
+
+ if (existsByName(organizationRequest.getName())) {
+ throw new RuntimeException("Organization with name: " + organizationRequest.getName() + " already exists.");
+ }
+
+ if (existsByCode(organizationRequest.getCode())) {
+ throw new RuntimeException("Organization with code: " + organizationRequest.getCode() + " already exists.");
+ }
+
+ User user = authService.getCurrentUser();
+ String orgUid = uidUtils.getCacheSerialUid();
+ //
+ Organization organization = modelMapper.map(organizationRequest, Organization.class);
+ organization.setUid(orgUid);
+ organization.setUser(user);
+ log.info("Creating organization: {}", organization.toString());
+ //
+ try {
+ //
+ Organization savedOrganization = save(organization);
+ if (savedOrganization == null) {
+ throw new RuntimeException("Failed to create organization.");
+ }
+ //
+ log.info("Organization created with UID: {}", orgUid);
+ // 初始化组织的角色
+ roleService.initOrgRoles(orgUid);
+ //
+ Optional roleOptional = roleService.findByNameAndOrgUid(TypeConsts.ROLE_ADMIN, orgUid);
+ if (roleOptional.isPresent()) {
+ log.info("roleOptional success");
+ user.addOrganizationRole(savedOrganization, roleOptional.get());
+ userService.save(user);
+ } else {
+ log.info("roleOptional fail");
+ }
+ // 放到listener中会报错,所以放在此处
+ bytedeskEventPublisher.publishOrganizationCreateEvent(organization);
+ //
+ return convertToResponse(savedOrganization);
+
+ } catch (Exception e) {
+ // 如果在事务中发生异常,则重新抛出以触发事务回滚
+ e.printStackTrace();
+ throw new RuntimeException("Error occurred during organization creation", e);
+ }
+ }
+
+ public OrganizationResponse update(OrganizationRequest organizationRequest) {
+
+ // 查找要更新的组织
+ Optional organizationOptional = findByUid(organizationRequest.getUid());
+ if (!organizationOptional.isPresent()) {
+ // 如果组织不存在,可以抛出一个自定义异常,例如OrganizationNotFoundException
+ throw new RuntimeException("Organization with UID: " + organizationRequest.getUid() + " not found.");
+ }
+
+ // 获取要更新的组织实体
+ Organization organization = organizationOptional.get();
+
+ // 使用ModelMapper进行属性拷贝,避免逐一设置字段
+ modelMapper.map(organizationRequest, organization);
+
+ // 保存更新后的组织
+ Organization updatedOrganization = save(organization);
+
+ if (updatedOrganization == null) {
+ throw new RuntimeException("Failed to update organization.");
+ }
+
+ // 转换为响应对象
+ return convertToResponse(updatedOrganization);
+ }
+
+ @Cacheable(value = "organization", key = "#uid", unless = "#result == null")
+ public Optional findByUid(String uid) {
+ return organizationRepository.findByUid(uid);
+ }
+
+ @Cacheable(value = "organization", key = "#name", unless = "#result == null")
+ public Optional findByName(String name) {
+ return organizationRepository.findByNameAndDeleted(name, false);
+ }
+
+ @Cacheable(value = "organization", key = "#code", unless = "#result == null")
+ public Optional findByCode(String code) {
+ return organizationRepository.findByCodeAndDeleted(code, false);
+ }
+
+ public Boolean existsByName(String name) {
+ return organizationRepository.existsByNameAndDeleted(name, false);
+ }
+
+ public Boolean existsByCode(String code) {
+ return organizationRepository.existsByCodeAndDeleted(code, false);
+ }
+
+ @Caching(put = {
+ @CachePut(value = "organization", key = "#organization.uid"),
+ @CachePut(value = "organization", key = "#organization.name")
+ })
+ public Organization save(Organization organization) {
+ try {
+ return organizationRepository.save(organization);
+ } catch (ObjectOptimisticLockingFailureException e) {
+ handleOptimisticLockingFailureException(e, organization);
+ }
+ return null;
+ }
+
+ public void handleOptimisticLockingFailureException(ObjectOptimisticLockingFailureException e,
+ Organization organization) {
+ log.info("handleOptimisticLockingFailureException: " + e.getMessage());
+ }
+
+ public OrganizationResponse convertToResponse(Organization organization) {
+ return modelMapper.map(organization, OrganizationResponse.class);
+ }
+
+ public void initData() {
+
+ if (organizationRepository.count() > 0) {
+ return;
+ }
+ //
+ Optional adminOptional = userService.getAdmin();
+ if (adminOptional.isPresent()) {
+ //
+ Organization organization = Organization.builder()
+ // .uid(uidUtils.getCacheSerialUid())
+ .name(bytedeskProperties.getOrganizationName())
+ .code(bytedeskProperties.getOrganizationCode())
+ .description(bytedeskProperties.getOrganizationName() + " Description")
+ .user(adminOptional.get())
+ .build();
+ // organization.setUid(uidUtils.getCacheSerialUid());
+ organization.setUid(UserConsts.DEFAULT_ORGANIZATION_UID);
+ save(organization);
+ //
+ // adminOptional.get().getOrganizations().add(organization.getUid());
+ // userService.save(adminOptional.get());
+ }
+
+ }
+
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationVerifyStatusEnum.java b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationVerifyStatusEnum.java
new file mode 100644
index 0000000000..93d65d31c2
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationVerifyStatusEnum.java
@@ -0,0 +1,21 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-06-11 15:57:05
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-11 15:57:08
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.rbac.organization;
+
+public enum OrganizationVerifyStatusEnum {
+ UNVERIFIED,
+ VERIFING,
+ VERIFIED;
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationVerifyTypeEnum.java b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationVerifyTypeEnum.java
new file mode 100644
index 0000000000..3dbc1f237f
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/organization/OrganizationVerifyTypeEnum.java
@@ -0,0 +1,22 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-06-11 15:58:36
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-11 15:59:39
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.rbac.organization;
+
+public enum OrganizationVerifyTypeEnum {
+ PERSONAL,
+ COMPANY,
+ GOVERMENT,
+ OTHER
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/role/Role.java b/modules/core/src/main/java/com/bytedesk/core/rbac/role/Role.java
index 7271628e04..65d320db77 100755
--- a/modules/core/src/main/java/com/bytedesk/core/rbac/role/Role.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/role/Role.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-29 16:21:24
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-10 23:25:43
+ * @LastEditTime: 2024-06-11 18:06:55
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -27,6 +27,7 @@ import java.util.Set;
import java.util.HashSet;
import com.bytedesk.core.base.BaseEntity;
+import com.bytedesk.core.constant.TypeConsts;
import com.bytedesk.core.rbac.authority.Authority;
import com.fasterxml.jackson.annotation.JsonIgnore;
@@ -38,28 +39,32 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
@Data
@Entity
@Builder
-@EqualsAndHashCode(callSuper=false)
+@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
-@Table(name = "core_role")
+@Table(name = "core_role", uniqueConstraints = {
+ @UniqueConstraint(columnNames = { "name", "orgUid" }),
+})
public class Role extends BaseEntity {
private static final long serialVersionUID = 1L;
-
+
@NotBlank
- @Column(unique = true, nullable = false)
+ @Column(nullable = false)
private String name;
+ private String displayName;
+
/**
* value is a keyword in h2 db
*/
- // @Column(name = "by_value", unique = true, nullable = false)
+ // @Column(name = "by_value", nullable = false)
// private String value;
private String description;
- @Column(name = "by_type")
+ @Column(name = TypeConsts.COLUMN_NAME_TYPE)
private String type;
@JsonIgnore
@@ -75,13 +80,12 @@ public class Role extends BaseEntity {
// @ManyToOne(fetch = FetchType.LAZY)
// @JsonBackReference("user-roles") // 避免无限递归
// private User user;
-
private String orgUid;
-
public void addAuthority(Authority authority) {
this.authorities.add(authority);
}
+
public void removeAuthority(Authority authority) {
this.authorities.remove(authority);
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/role/RoleController.java b/modules/core/src/main/java/com/bytedesk/core/rbac/role/RoleController.java
index 84b4a42e2f..b6e8bc2660 100644
--- a/modules/core/src/main/java/com/bytedesk/core/rbac/role/RoleController.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/role/RoleController.java
@@ -34,16 +34,16 @@ import com.bytedesk.core.utils.JsonResult;
public class RoleController {
private final RoleService roleService;
-
+
/**
* query my roles by page
*
* @return json
*/
- @GetMapping("/query")
- public ResponseEntity> query(RoleRequest roleRequest) {
+ @GetMapping("/query/org")
+ public ResponseEntity> queryByOrg(RoleRequest roleRequest) {
- Page rolePage = roleService.query(roleRequest);
+ Page rolePage = roleService.queryByOrg(roleRequest);
//
return ResponseEntity.ok(JsonResult.success(rolePage));
}
@@ -70,11 +70,11 @@ public class RoleController {
*/
// @PostMapping("/update")
// public Callable> update(@RequestBody RoleParam roleParam) {
- // return () -> {
- // RoleDTO roleDTO = roleService.update(roleParam);
- // //
- // return new JsonResult<>("更新角色成功", 200, roleDTO);
- // };
+ // return () -> {
+ // RoleDTO roleDTO = roleService.update(roleParam);
+ // //
+ // return new JsonResult<>("更新角色成功", 200, roleDTO);
+ // };
// }
/**
@@ -85,11 +85,11 @@ public class RoleController {
*/
// @PostMapping("/delete")
// public Callable> delete(@RequestBody RoleParam roleParam) {
- // return () -> {
- // roleService.deleteById(roleParam.getId());
+ // return () -> {
+ // roleService.deleteById(roleParam.getId());
- // return new JsonResult<>("删除角色成功", 200, roleParam.getId());
- // };
+ // return new JsonResult<>("删除角色成功", 200, roleParam.getId());
+ // };
// }
/**
@@ -99,11 +99,12 @@ public class RoleController {
*/
// @GetMapping("/filter")
// public Callable> filter(FilterParam filterParam) {
- // return () -> {
- // Page roleDTOPage = roleService.findByNameContainingOrValueContainingAndUser(filterParam);
- // //
- // return new JsonResult<>("搜索角色成功", 200, roleDTOPage);
- // };
+ // return () -> {
+ // Page roleDTOPage =
+ // roleService.findByNameContainingOrValueContainingAndUser(filterParam);
+ // //
+ // return new JsonResult<>("搜索角色成功", 200, roleDTOPage);
+ // };
// }
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/role/RoleRepository.java b/modules/core/src/main/java/com/bytedesk/core/rbac/role/RoleRepository.java
index d6bdbd534d..8f47260d81 100644
--- a/modules/core/src/main/java/com/bytedesk/core/rbac/role/RoleRepository.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/role/RoleRepository.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-29 16:21:24
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-04-24 10:14:30
+ * @LastEditTime: 2024-06-11 17:36:16
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -36,14 +36,14 @@ import java.util.Optional;
@Tag(name = "roles - 角色")
public interface RoleRepository extends JpaRepository, JpaSpecificationExecutor {
- Optional findByName(String name);
+ Optional findByNameAndOrgUidAndDeleted(String name, String orgUid, Boolean deleted);
- List findByType(String type);
+ List findByTypeAndOrgUidAndDeleted(String type, String orgUid, Boolean deleted);
// Page findByUser(User user, Pageable pageable);
- Page findByOrgUid(String orgUid, Pageable pageable);
+ Page findByOrgUidAndDeleted(String orgUid, boolean deleted, Pageable pageable);
- Boolean existsByName(String name);
+ Boolean existsByNameAndOrgUidAndDeleted(String name, String orgUid, boolean deleted);
@Transactional
void deleteById(@NonNull Long id);
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/role/RoleRequest.java b/modules/core/src/main/java/com/bytedesk/core/rbac/role/RoleRequest.java
index 93eb126ce9..2f19fea50a 100644
--- a/modules/core/src/main/java/com/bytedesk/core/rbac/role/RoleRequest.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/role/RoleRequest.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-29 16:21:24
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-04 10:40:03
+ * @LastEditTime: 2024-06-11 17:47:19
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -30,20 +30,18 @@ import com.bytedesk.core.base.BaseRequest;
@EqualsAndHashCode(callSuper = false)
public class RoleRequest extends BaseRequest {
- // private String rid;
-
private String name;
+ private String displayName;
+
// private String value;
private String description;
@Builder.Default
- private Set authorityAids = new HashSet<>();
+ private Set authorityUids = new HashSet<>();
// organization oid
private String orgUid;
-
-
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/role/RoleResponse.java b/modules/core/src/main/java/com/bytedesk/core/rbac/role/RoleResponse.java
index 335a73472f..b43b7e3c4c 100644
--- a/modules/core/src/main/java/com/bytedesk/core/rbac/role/RoleResponse.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/role/RoleResponse.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-29 16:21:24
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-04 10:40:07
+ * @LastEditTime: 2024-05-23 09:15:31
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -38,12 +38,12 @@ import com.bytedesk.core.rbac.authority.AuthorityResponse;
@EqualsAndHashCode(callSuper = true)
public class RoleResponse extends BaseResponse {
- private static final long serialVersionUID = 4082434575L;
-
- // private String rid;
+ private static final long serialVersionUID = 1L;
private String name;
+ private String displayName;
+
// private String value;
private String description;
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/role/RoleService.java b/modules/core/src/main/java/com/bytedesk/core/rbac/role/RoleService.java
index 5bc572e876..4fe53d0ae7 100644
--- a/modules/core/src/main/java/com/bytedesk/core/rbac/role/RoleService.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/role/RoleService.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-29 16:21:24
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-13 11:04:38
+ * @LastEditTime: 2024-06-11 18:14:34
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -25,19 +25,17 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
+import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
-import com.bytedesk.core.config.BytedeskProperties;
-import com.bytedesk.core.constant.BdConstants;
+import com.bytedesk.core.constant.I18Consts;
import com.bytedesk.core.constant.TypeConsts;
+import com.bytedesk.core.constant.UserConsts;
import com.bytedesk.core.rbac.authority.Authority;
import com.bytedesk.core.rbac.authority.AuthorityService;
-import com.bytedesk.core.rbac.user.User;
-import com.bytedesk.core.rbac.user.UserRepository;
import com.bytedesk.core.uid.UidUtils;
-import com.bytedesk.core.utils.BdConvertUtils;
+import com.bytedesk.core.utils.ConvertUtils;
-import java.util.Arrays;
import java.util.Iterator;
import java.util.Optional;
@@ -48,10 +46,6 @@ public class RoleService {
private final RoleRepository roleRepository;
- private final UserRepository userRepository;
-
- private final BytedeskProperties properties;
-
private final ModelMapper modelMapper;
private final UidUtils uidUtils;
@@ -60,17 +54,17 @@ public class RoleService {
public Role create(RoleRequest rolerRequest) {
- if (existsByName(rolerRequest.getName())) {
+ if (existsByNameAndOrgUid(rolerRequest.getName(), rolerRequest.getOrgUid())) {
throw new RuntimeException("角色已存在");
}
Role role = modelMapper.map(rolerRequest, Role.class);
role.setUid(uidUtils.getCacheSerialUid());
//
- Iterator iterator = rolerRequest.getAuthorityAids().iterator();
+ Iterator iterator = rolerRequest.getAuthorityUids().iterator();
while (iterator.hasNext()) {
- String authorityAid = iterator.next();
- Optional authorityOptional = authorityService.findByAid(authorityAid);
+ String authorityUid = iterator.next();
+ Optional authorityOptional = authorityService.findByUid(authorityUid);
if (authorityOptional.isPresent()) {
role.addAuthority(authorityOptional.get());
}
@@ -79,84 +73,78 @@ public class RoleService {
return save(role);
}
- public Page query(RoleRequest roleRequest) {
+ public Page queryByOrg(RoleRequest roleRequest) {
Pageable pageable = PageRequest.of(roleRequest.getPageNumber(), roleRequest.getPageSize(),
- Sort.Direction.DESC,
+ Sort.Direction.ASC,
"id");
- Page rolePage = roleRepository.findByOrgUid(roleRequest.getOrgUid(), pageable);
+ Specification specification = RoleSpecification.search(roleRequest);
+ Page rolePage = roleRepository.findAll(specification, pageable);
+ // Page rolePage = roleRepository.findByOrgUidAndDeleted(roleRequest.getOrgUid(), false, pageable);
- return rolePage.map(BdConvertUtils::convertToRoleResponse);
+ return rolePage.map(ConvertUtils::convertToRoleResponse);
}
- @Cacheable(value = "roleExists", key = "#name", unless = "#result == null")
- public Boolean existsByName(String namString) {
- return roleRepository.existsByName(namString);
+ @Cacheable(value = "roleExists", key = "#name + '-' + #orgUid", unless = "#result == null")
+ public Boolean existsByNameAndOrgUid(String name, String orgUid) {
+ return roleRepository.existsByNameAndOrgUidAndDeleted(name, orgUid, false);
}
- @Cacheable(value = "role", key = "#name", unless = "#result == null")
- public Optional findByName(String name) {
- return roleRepository.findByName(name);
+ @Cacheable(value = "role", key = "#name + '-' + #orgUid", unless = "#result == null")
+ public Optional findByNameAndOrgUid(String name, String orgUid) {
+ return roleRepository.findByNameAndOrgUidAndDeleted(name, orgUid, false);
}
@Caching(put = {
- @CachePut(value = "role", key = "#role.name"),
- // TODO: 此处put的exists内容跟缓存时内容类型是否一致?
- // @CachePut(value = "roleExists", key = "#role.name")
+ @CachePut(value = "role", key = "#role.name+ '-' + #role.orgUid"),
})
public Role save(Role role) {
return roleRepository.save(role);
}
- //
- private static final String[] authorities = {
- TypeConsts.AUTHORITY_SUPER,
- TypeConsts.AUTHORITY_ADMIN,
- TypeConsts.AUTHORITY_HR,
- TypeConsts.AUTHORITY_ORG,
- TypeConsts.AUTHORITY_IT,
- TypeConsts.AUTHORITY_MONEY,
- TypeConsts.AUTHORITY_MARKETING,
- TypeConsts.AUTHORITY_SALES,
- TypeConsts.AUTHORITY_CUSTOMER_SERVICE,
- };
-
- public void initData() {
- if (roleRepository.count() > 0) {
- // log.debug("role already exists");
- return;
- }
+ public void initOrgRoles(String orgUid) {
//
for (String authority : authorities) {
- String role = TypeConsts.ROLE_PREFIX + authority;
- RoleRequest roleRequest = RoleRequest.builder().name(role).description(role).build();
+ String name = TypeConsts.ROLE_PREFIX + authority;
+ String displayName = I18Consts.I18N_PREFIX + name;
+ RoleRequest roleRequest = RoleRequest.builder()
+ .name(name)
+ .displayName(displayName)
+ .orgUid(orgUid)
+ .description(name)
+ .build();
roleRequest.setType(TypeConsts.TYPE_SYSTEM);
//
Optional authorityOptional = authorityService.findByValue(authority);
if (authorityOptional.isPresent()) {
- roleRequest.getAuthorityAids().add(authorityOptional.get().getUid());
+ roleRequest.getAuthorityUids().add(authorityOptional.get().getUid());
}
//
create(roleRequest);
}
}
- public void updateInitData() {
- //
- Optional adminOptional = userRepository.findByEmailAndPlatform(properties.getEmail(), BdConstants.PLATFORM_BYTEDESK);
- if (adminOptional.isPresent()) {
- //
- Arrays.stream(authorities).forEach((authority) -> {
- String roleName = TypeConsts.ROLE_PREFIX + authority;
- Optional roleOptional = findByName(roleName);
- roleOptional.ifPresent(role -> {
- role.setOrgUid(adminOptional.get().getOrgUid());
- roleRepository.save(role);
- });
- });
- }
+ //
+ private static final String[] authorities = {
+ TypeConsts.SUPER,
+ TypeConsts.ADMIN,
+ TypeConsts.HR,
+ TypeConsts.ORG,
+ TypeConsts.IT,
+ TypeConsts.MONEY,
+ TypeConsts.MARKETING,
+ TypeConsts.SALES,
+ TypeConsts.CUSTOMER_SERVICE,
+ };
+ public void initData() {
+ //
+ if (roleRepository.count() > 0) {
+ return;
+ }
+ //
+ initOrgRoles(UserConsts.DEFAULT_ORGANIZATION_UID);
}
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/role/RoleSpecification.java b/modules/core/src/main/java/com/bytedesk/core/rbac/role/RoleSpecification.java
new file mode 100644
index 0000000000..25c2fa7783
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/role/RoleSpecification.java
@@ -0,0 +1,43 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-06-11 18:13:47
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-11 18:13:49
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.rbac.role;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.data.jpa.domain.Specification;
+
+import com.bytedesk.core.base.BaseSpecification;
+
+import jakarta.persistence.criteria.Predicate;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class RoleSpecification extends BaseSpecification {
+
+ public static Specification search(RoleRequest request) {
+ log.info("request: {}", request);
+ return (root, query, criteriaBuilder) -> {
+ List predicates = new ArrayList<>();
+ predicates.addAll(getBasicPredicates(root, criteriaBuilder, request.getOrgUid()));
+ //
+ // if (StringUtils.hasText(request.getClient())) {
+ // predicates.add(criteriaBuilder.like(root.get("client"), "%" + request.getClient() + "%"));
+ // }
+ //
+ return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
+ };
+ }
+}
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/user/User.java b/modules/core/src/main/java/com/bytedesk/core/rbac/user/User.java
index 61319c1862..597f6b5afa 100644
--- a/modules/core/src/main/java/com/bytedesk/core/rbac/user/User.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/user/User.java
@@ -9,19 +9,21 @@ import org.hibernate.type.SqlTypes;
import com.bytedesk.core.base.BaseEntity;
import com.bytedesk.core.constant.AvatarConsts;
import com.bytedesk.core.constant.BdConstants;
+import com.bytedesk.core.constant.I18Consts;
+import com.bytedesk.core.constant.TypeConsts;
+import com.bytedesk.core.rbac.organization.Organization;
import com.bytedesk.core.rbac.role.Role;
-import com.bytedesk.core.utils.StringSetConverter;
import com.fasterxml.jackson.annotation.JsonIgnore;
+
+import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
-import jakarta.persistence.Convert;
import jakarta.persistence.Entity;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.FetchType;
-import jakarta.persistence.ManyToMany;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
-// import jakarta.persistence.UniqueConstraint;
-// import jakarta.validation.constraints.Digits;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
@@ -35,16 +37,18 @@ import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
@Builder
-@EqualsAndHashCode(callSuper = true)
+// "roles",
+@EqualsAndHashCode(callSuper = true, exclude = { "password", "currentOrganization", "userOrganizationRoles" })
@AllArgsConstructor
@NoArgsConstructor
-@EntityListeners({ UserListener.class })
+@EntityListeners({ UserEntityListener.class })
+// @DiscriminatorValue("User")
@Table(name = "core_user", uniqueConstraints = {
- // num, username, email, mobile 在各个平台唯一
- @UniqueConstraint(columnNames = { "num", "platform" }),
- @UniqueConstraint(columnNames = { "username", "platform" }),
- @UniqueConstraint(columnNames = { "email", "platform" }),
- @UniqueConstraint(columnNames = { "mobile", "platform" }),
+ // num, username, email, mobile is unique combined with platform, not self
+ @UniqueConstraint(columnNames = { "num", "platform" }),
+ @UniqueConstraint(columnNames = { "username", "platform" }),
+ @UniqueConstraint(columnNames = { "email", "platform" }),
+ @UniqueConstraint(columnNames = { "mobile", "platform" }),
})
public class User extends BaseEntity {
@@ -55,7 +59,6 @@ public class User extends BaseEntity {
// used in authjwtToken, should not be null
@NotBlank(message = "username is required")
- // unique = true,
@Column(nullable = false)
private String username;
@@ -77,7 +80,13 @@ public class User extends BaseEntity {
private String avatar = AvatarConsts.DEFAULT_AVATAR_URL;
@Builder.Default
- private String description = BdConstants.DEFAULT_USER_DESCRIPTION;
+ private String description = I18Consts.I18N_USER_DESCRIPTION;
+
+ // @Embedded
+ // private UserSettings userSettings;
+
+ @Builder.Default
+ private Sex sex = Sex.UNKNOW;
@Builder.Default
@Column(name = "is_enabled")
@@ -98,38 +107,89 @@ public class User extends BaseEntity {
@Builder.Default
private String platform = BdConstants.PLATFORM_BYTEDESK;
- @Builder.Default
- @ManyToMany(fetch = FetchType.EAGER)
- private Set roles = new HashSet<>();
-
- @Builder.Default
- @Convert(converter = StringSetConverter.class)
- private Set organizations = new HashSet<>();
+ // @Builder.Default
+ // @ManyToMany(fetch = FetchType.EAGER)
+ // private Set roles = new HashSet<>();
+
+ // // TODO: restrict one user to one org? to be determinated which make roles
+ // complicated
+ // @Builder.Default
+ // @Convert(converter = StringSetConverter.class)
+ // private Set organizations = new HashSet<>();
+
+ //
+ @JsonIgnore
+ @ManyToOne(fetch = FetchType.LAZY)
+ private Organization currentOrganization;
@Builder.Default
- @Column(columnDefinition = "json")
- // 用于兼容postgreSQL,否则会报错,[ERROR: column "extra" is of type json but expression is of type character varying
- @JdbcTypeCode(SqlTypes.JSON)
- private String extra = BdConstants.EMPTY_JSON_STRING;
+ @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
+ private Set userOrganizationRoles = new HashSet<>();
+
+ // 添加方法以简化对用户组织和角色的管理
+ public void addOrganizationRole(Organization organization, Role role) {
+ UserOrganizationRole uor = UserOrganizationRole.builder().user(this).organization(organization).role(role)
+ .build();
+ this.userOrganizationRoles.add(uor);
+ //
+ if (this.currentOrganization == null) {
+ this.currentOrganization = organization;
+ }
+ }
+
+ public void removeOrganizationRole(Organization organization, Role role) {
+ UserOrganizationRole uor = UserOrganizationRole.builder().user(this).organization(organization).role(role)
+ .build();
+ if (this.userOrganizationRoles.contains(uor)) {
+ this.userOrganizationRoles.remove(uor);
+ }
+ }
+
+ @Builder.Default
+ @Column(columnDefinition = TypeConsts.COLUMN_TYPE_JSON)
+ // 用于兼容postgreSQL,否则会报错,[ERROR: column "extra" is of type json but expression is
+ // of type character varying
+ @JdbcTypeCode(SqlTypes.JSON)
+ private String extra = BdConstants.EMPTY_JSON_STRING;
// return the first organization oid
public String getOrgUid() {
- return this.organizations.isEmpty() ? null : this.organizations.iterator().next();
- }
-
- /** */
- public void addRole(Role role) {
- if (!this.roles.contains(role)) {
- this.roles.add(role);
- // role.getUsers().add(this);
- }
- }
-
- public void removeRole(Role role) {
- if (this.roles.contains(role)) {
- this.roles.remove(role);
- // role.getUsers().remove(this);
+ if (this.currentOrganization == null) {
+ return BdConstants.EMPTY_STRING;
}
+ return this.currentOrganization.getUid();
}
-
+
+ // /** */
+ // public void addRole(Role role) {
+ // if (!this.roles.contains(role)) {
+ // this.roles.add(role);
+ // // role.getUsers().add(this);
+ // }
+ // }
+
+ // public void removeRole(Role role) {
+ // if (this.roles.contains(role)) {
+ // this.roles.remove(role);
+ // // role.getUsers().remove(this);
+ // }
+ // }
+
+ //
+ // 定义性别枚举
+ public enum Sex {
+ MALE,
+ FEMALE,
+ UNKNOW // unknown
+ }
+
+ @Override
+ public String toString() {
+ return "User [uid=" + this.getUid() +
+ ", username=" + this.username +
+ ", email=" + this.email +
+ ", mobile=" + this.mobile +
+ "]";
+ }
+
}
\ No newline at end of file
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserController.java b/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserController.java
index 0d5d5e326c..db667d3d9c 100644
--- a/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserController.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserController.java
@@ -18,7 +18,9 @@ import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
+import com.bytedesk.core.action.ActionAnnotation;
import com.bytedesk.core.rbac.auth.AuthService;
+import com.bytedesk.core.utils.ConvertUtils;
import com.bytedesk.core.utils.JsonResult;
import lombok.AllArgsConstructor;
@@ -42,10 +44,10 @@ public class UserController {
*/
@GetMapping("/profile")
public ResponseEntity> getProfile() {
- //
+ //
User user = authService.getCurrentUser();
- UserResponse userResponse = userService.convertToUserResponse(user);
+ UserResponse userResponse = ConvertUtils.convertToUserResponse(user);
return ResponseEntity.ok(JsonResult.success(userResponse));
}
@@ -56,6 +58,7 @@ public class UserController {
* @param userRequest
* @return
*/
+ @ActionAnnotation(title = "user", action = "update", description = "update user info")
@PostMapping("/update")
public ResponseEntity> update(@RequestBody UserRequest userRequest) {
@@ -65,19 +68,20 @@ public class UserController {
}
/** */
+ @ActionAnnotation(title = "user", action = "logout", description = "logout")
@PostMapping("/logout")
- public ResponseEntity logout() {
+ public ResponseEntity> logout() {
// TODO: 清理token,使其过期
- return ResponseEntity.ok().body("logout");
+ return ResponseEntity.ok().body(JsonResult.success());
}
-
+
/** for testing,client will return 403, if dont have authority/role */
@PreAuthorize("hasAnyAuthority('ROLE_SUPER', 'ROLE_ADMIN')")
// @PreAuthorize("hasAuthority('ROLE_SUPER') or hasAuthority('ROLE_ADMIN')")
// @PreAuthorize("hasAuthority('ROLE_SUPER')")
@GetMapping("/test/super")
public ResponseEntity> testSuperAuthority() {
- return ResponseEntity.ok("you have super authority");
+ return ResponseEntity.ok("you have super authority");
}
/** no need to add ROLE_ prefix, system will auto add */
@@ -88,5 +92,4 @@ public class UserController {
return ResponseEntity.ok("you have admin or cs role");
}
-
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserDetailsImpl.java b/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserDetailsImpl.java
index 3325a36f63..58a6b02f14 100644
--- a/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserDetailsImpl.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserDetailsImpl.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-23 07:53:01
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-13 11:47:22
+ * @LastEditTime: 2024-06-03 11:04:15
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -18,8 +18,7 @@ import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
-import com.bytedesk.core.constant.TypeConsts;
-import com.bytedesk.core.rbac.role.Role;
+import com.bytedesk.core.rbac.organization.Organization;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
@@ -47,15 +46,21 @@ public class UserDetailsImpl implements UserDetails {
//
@JsonIgnore
private String password;
- private Set roles;
- private Set organizations;
+ private Organization currentOrganization;
+ private Set userOrganizationRoles;
+ // private Set roles;
+ // private Set organizations;
//
private boolean enabled;
Collection extends GrantedAuthority> authorities;
private UserDetailsImpl(Long id, String uid, String username, String nickname, String avatar, String mobile,
String email, String password,
- Collection extends GrantedAuthority> authorities, Set roles, Set organizations,
+ Collection extends GrantedAuthority> authorities,
+ Organization currentOrganization,
+ Set userOrganizationRoles,
+ // Set roles,
+ // Set organizations,
String description,
boolean superUser,
boolean emailVerified,
@@ -71,8 +76,10 @@ public class UserDetailsImpl implements UserDetails {
this.email = email;
this.password = password;
this.authorities = authorities;
- this.roles = roles;
- this.organizations = organizations;
+ this.currentOrganization = currentOrganization;
+ this.userOrganizationRoles = userOrganizationRoles;
+ // this.roles = roles;
+ // this.organizations = organizations;
this.description = description;
//
this.superUser = superUser;
@@ -89,9 +96,15 @@ public class UserDetailsImpl implements UserDetails {
// Set authorities = user.getRoles().stream()
// .map(role -> new SimpleGrantedAuthority(role.getValue()))
// .collect(Collectors.toSet());
- Set authorities = user.getRoles().stream()
- .flatMap(role -> role.getAuthorities().stream()
- .map(authority -> new SimpleGrantedAuthority(TypeConsts.ROLE_PREFIX + authority.getValue())))
+ //
+ // Set authorities = user.getRoles().stream()
+ // .flatMap(role -> role.getAuthorities().stream()
+ // .map(authority -> new SimpleGrantedAuthority(TypeConsts.ROLE_PREFIX + authority.getValue())))
+ // .collect(Collectors.toSet());
+ //
+ Set authorities = user.getUserOrganizationRoles().stream()
+ .flatMap(uor -> uor.getRole().getAuthorities().stream()
+ .map(authority -> new SimpleGrantedAuthority(authority.getValue())))
.collect(Collectors.toSet());
return new UserDetailsImpl(user.getId(),
@@ -103,8 +116,10 @@ public class UserDetailsImpl implements UserDetails {
user.getEmail(),
user.getPassword(),
authorities,
- user.getRoles(),
- user.getOrganizations(),
+ user.getCurrentOrganization(),
+ user.getUserOrganizationRoles(),
+ // user.getRoles(),
+ // user.getOrganizations(),
user.getDescription(),
user.isSuperUser(),
user.isEmailVerified(),
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserDetailsServiceImpl.java b/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserDetailsServiceImpl.java
index 4039705266..e954c7afb6 100644
--- a/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserDetailsServiceImpl.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserDetailsServiceImpl.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-23 07:53:01
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-13 14:22:31
+ * @LastEditTime: 2024-05-23 13:45:21
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -43,8 +43,6 @@ public class UserDetailsServiceImpl implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
- // String username = JSON.parseObject(subject, JwtSubject.class).getUsername();
- // String platform = JSON.parseObject(subject, JwtSubject.class).getPlatform();
log.debug("loadUserByUsername {}", username);
//
Optional userOptional = userService.findByUsernameAndPlatform(username, BdConstants.PLATFORM_BYTEDESK);
@@ -57,7 +55,7 @@ public class UserDetailsServiceImpl implements UserDetailsService {
return UserDetailsImpl.build(userOptional.get());
}
- public UserDetails loadUserByUsernameAndPlatform(String subject) throws UsernameNotFoundException {
+ public UserDetails loadUserByUsernameAndPlatform(String subject) {
String username = JSON.parseObject(subject, JwtSubject.class).getUsername();
String platform = JSON.parseObject(subject, JwtSubject.class).getPlatform();
log.debug("loadUserByUsername {}, username {}, platform {}", subject, username, platform);
@@ -72,7 +70,7 @@ public class UserDetailsServiceImpl implements UserDetailsService {
return UserDetailsImpl.build(userOptional.get());
}
- public UserDetailsImpl loadUserByEmailAndPlatform(String email, String platform) throws EmailNotFoundException {
+ public UserDetailsImpl loadUserByEmailAndPlatform(String email, String platform) {
log.debug("loadUserByEmail {}", email);
//
Optional userOptional = userService.findByEmailAndPlatform(email, platform);
@@ -85,7 +83,7 @@ public class UserDetailsServiceImpl implements UserDetailsService {
return UserDetailsImpl.build(userOptional.get());
}
- public UserDetailsImpl loadUserByMobileAndPlatform(String mobile, String platform) throws MobileNotFoundException {
+ public UserDetailsImpl loadUserByMobileAndPlatform(String mobile, String platform) {
log.debug("loadUserByMobile {}", mobile);
//
Optional userOptional = userService.findByMobileAndPlatform(mobile, platform);
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserListener.java b/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserEntityListener.java
similarity index 69%
rename from modules/core/src/main/java/com/bytedesk/core/rbac/user/UserListener.java
rename to modules/core/src/main/java/com/bytedesk/core/rbac/user/UserEntityListener.java
index 207e491cb1..45fbc440cc 100644
--- a/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserListener.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserEntityListener.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-04-15 09:30:09
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-08 10:53:08
+ * @LastEditTime: 2024-06-12 07:24:24
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -17,7 +17,7 @@ package com.bytedesk.core.rbac.user;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
-import com.bytedesk.core.thread.ThreadService;
+// import com.bytedesk.core.thread.ThreadService;
import com.bytedesk.core.topic.TopicService;
import com.bytedesk.core.utils.ApplicationContextHolder;
import jakarta.persistence.PostPersist;
@@ -26,7 +26,7 @@ import lombok.extern.slf4j.Slf4j;
@Async
@Slf4j
@Component
-public class UserListener {
+public class UserEntityListener {
// 无法注入bean,否则报错
// private static TopicService topicService;
@@ -38,30 +38,32 @@ public class UserListener {
// create user topic
TopicService topicService = ApplicationContextHolder.getBean(TopicService.class);
topicService.create(user.getUid(), user.getUid());
- // 每创建一个用户,自动给此用户生成一条文件助理的会话
- ThreadService threadService = ApplicationContextHolder.getBean(ThreadService.class);
- threadService.createAsistantThread(user);
+ // // 每创建一个用户,自动给此用户生成一条文件助理的会话
+ // ThreadService threadService = ApplicationContextHolder.getBean(ThreadService.class);
+ // threadService.createFileAsistantThread(user);
+ // // 每创建一个用户,自动给此用户生成一条系统通知的会话
+ // threadService.createSystemNotificationChannelThread(user);
}
// @PreUpdate
// public void preUpdate(User user) {
- // log.info("preUpdate {}", user.getUid());
+ // log.info("preUpdate {}", user.getUid());
// }
// @PostUpdate
// public void postUpdate(User user) {
- // log.info("postUpdate {}", user.getUid());
+ // log.info("postUpdate {}", user.getUid());
// }
// @PreRemove
// public void preRemove(User user) {
- // log.info("preRemove {}", user.getUid());
+ // log.info("preRemove {}", user.getUid());
// }
// @PostRemove
// public void postRemove(User user) {
- // log.info("postRemove {}", user.getUid());
- // // topicService.deleteByTopicAndUid(user.getUid(), user.getUid());
+ // log.info("postRemove {}", user.getUid());
+ // // topicService.deleteByTopicAndUid(user.getUid(), user.getUid());
// }
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserOrganizationRole.java b/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserOrganizationRole.java
new file mode 100644
index 0000000000..034507eb5a
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserOrganizationRole.java
@@ -0,0 +1,59 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2024-06-03 09:19:22
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2024-06-03 15:05:43
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ * 联系:270580156@qq.com
+ * Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.rbac.user;
+
+import com.bytedesk.core.rbac.organization.Organization;
+import com.bytedesk.core.rbac.role.Role;
+
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+@Entity
+@Data
+@EqualsAndHashCode(callSuper=false, exclude = { "user", "organization", "role" })
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Table(name = "core_user_org_role")
+public class UserOrganizationRole {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Long id;
+
+ @ManyToOne
+ @JoinColumn(name = "user_id")
+ private User user;
+
+ @ManyToOne
+ @JoinColumn(name = "organization_id")
+ private Organization organization;
+
+ @ManyToOne
+ @JoinColumn(name = "role_id")
+ private Role role;
+
+ // 可能还有其他字段,如权限、有效期等
+}
diff --git a/modules/socket/src/main/java/com/bytedesk/socket/mqtt/model/MqttSubscribe.java b/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserOrganizationRoleResponse.java
old mode 100755
new mode 100644
similarity index 66%
rename from modules/socket/src/main/java/com/bytedesk/socket/mqtt/model/MqttSubscribe.java
rename to modules/core/src/main/java/com/bytedesk/core/rbac/user/UserOrganizationRoleResponse.java
index fe76c405ac..03703d0912
--- a/modules/socket/src/main/java/com/bytedesk/socket/mqtt/model/MqttSubscribe.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserOrganizationRoleResponse.java
@@ -1,8 +1,8 @@
/*
* @Author: jackning 270580156@qq.com
- * @Date: 2024-01-29 16:21:46
+ * @Date: 2024-06-03 10:20:01
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-02-26 13:42:09
+ * @LastEditTime: 2024-06-03 11:06:02
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -12,27 +12,25 @@
* 联系:270580156@qq.com
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
*/
-package com.bytedesk.socket.mqtt.model;
+package com.bytedesk.core.rbac.user;
-import java.io.Serializable;
+import com.bytedesk.core.rbac.organization.OrganizationResponse;
+import com.bytedesk.core.rbac.role.RoleResponse;
import lombok.AllArgsConstructor;
+import lombok.Builder;
import lombok.Data;
+import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
-/**
- * 订阅存储实体类
- */
@Data
+@Builder
@Accessors(chain = true)
@AllArgsConstructor
-public class MqttSubscribe implements Serializable {
+@NoArgsConstructor
+public class UserOrganizationRoleResponse {
- private static final long serialVersionUID = 1276156087085594264L;
+ private OrganizationResponse organization;
- private String clientId;
-
- private String topicFilter;
-
- private int mqttQoS;
+ private RoleResponse role;
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserRepository.java b/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserRepository.java
index 7fb999d650..0615f80f5f 100644
--- a/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserRepository.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserRepository.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-29 16:21:24
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-13 10:55:48
+ * @LastEditTime: 2024-06-04 15:57:00
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -32,11 +32,11 @@ import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository {
- Optional findByEmailAndPlatform(String email, String platform);
+ Optional findByEmailAndPlatformAndDeleted(String email, String platform, Boolean deleted);
- Optional findByMobileAndPlatform(String mobile, String platform);
+ Optional findByMobileAndPlatformAndDeleted(String mobile, String platform, Boolean deleted);
- Optional findByUsernameAndPlatform(String username, String platform);
+ Optional findByUsernameAndPlatformAndDeleted(String username, String platform, Boolean deleted);
Optional findByUid(String uid);
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserRequest.java b/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserRequest.java
index 99410347b7..1fe36975b2 100644
--- a/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserRequest.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserRequest.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-29 16:21:24
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-13 10:50:59
+ * @LastEditTime: 2024-06-03 09:58:47
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -16,7 +16,8 @@ package com.bytedesk.core.rbac.user;
import com.bytedesk.core.base.BaseRequest;
import com.bytedesk.core.constant.AvatarConsts;
-import com.bytedesk.core.constant.BdConstants;
+import com.bytedesk.core.constant.I18Consts;
+import com.bytedesk.core.rbac.user.User.Sex;
// import jakarta.validation.constraints.Digits;
import jakarta.validation.constraints.Email;
@@ -50,13 +51,17 @@ public class UserRequest extends BaseRequest {
// country prefix, e.g. +86
// @Digits(message = "phone length error", fraction = 0, integer = 11)
private String mobile;
+
private String code;
@Builder.Default
private String avatar = AvatarConsts.DEFAULT_AVATAR_URL;
@Builder.Default
- private String description = BdConstants.DEFAULT_USER_DESCRIPTION;
+ private String description = I18Consts.I18N_USER_DESCRIPTION;
+
+ @Builder.Default
+ private Sex sex = Sex.UNKNOW;
private Boolean enabled;
@@ -67,4 +72,6 @@ public class UserRequest extends BaseRequest {
@NotBlank(message = "platform required")
private String platform;
+ private String orgUid;
+
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserResponse.java b/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserResponse.java
index ea6a656340..82aedc65cf 100644
--- a/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserResponse.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserResponse.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-29 16:21:24
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-13 09:44:26
+ * @LastEditTime: 2024-06-03 11:29:48
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -21,11 +21,13 @@ import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
-import java.util.HashSet;
import java.util.Set;
+import org.springframework.security.core.GrantedAuthority;
+
import com.bytedesk.core.base.BaseResponse;
-import com.bytedesk.core.rbac.role.RoleResponse;
+import com.bytedesk.core.rbac.organization.OrganizationResponse;
+import com.bytedesk.core.rbac.user.User.Sex;
@Data
@Builder
@@ -35,7 +37,7 @@ import com.bytedesk.core.rbac.role.RoleResponse;
@EqualsAndHashCode(callSuper = true)
public class UserResponse extends BaseResponse {
- private static final long serialVersionUID = 1L;
+ private static final long serialVersionUID = 1L;
private String username;
private String nickname;
@@ -44,16 +46,23 @@ public class UserResponse extends BaseResponse {
private String avatar;
private String description;
private String platform;
- //
- private Boolean enabled;
- private boolean superUser;
- private Boolean emailVerified;
- private Boolean mobileVerified;
-
//
- @Builder.Default
- private Set roles = new HashSet<>();
+ private Sex sex;
+ private Boolean enabled;
+ private boolean superUser;
+ private Boolean emailVerified;
+ private Boolean mobileVerified;
+ //
+ private OrganizationResponse currentOrganization;
- @Builder.Default
- private Set organizations = new HashSet<>();
+ private Set userOrganizationRoles;
+
+ // used by other plafroms other than bytedesk, like liangshibao/tiku/zhaobiao
+ private Set authorities;
+ //
+ // @Builder.Default
+ // private Set roles = new HashSet<>();
+
+ // @Builder.Default
+ // private Set organizations = new HashSet<>();
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserResponseSimple.java b/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserResponseSimple.java
index a06f2098f2..395ab4339a 100644
--- a/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserResponseSimple.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserResponseSimple.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-29 16:21:24
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-13 09:40:39
+ * @LastEditTime: 2024-06-06 12:53:29
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -34,5 +34,6 @@ public class UserResponseSimple extends BaseResponse {
private static final long serialVersionUID = 1L;
private String nickname;
+
private String avatar;
}
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserService.java b/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserService.java
index 98a2009d86..c7a3897d71 100644
--- a/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserService.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserService.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-29 16:21:24
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-05-20 09:41:26
+ * @LastEditTime: 2024-06-04 15:57:38
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -15,8 +15,6 @@
package com.bytedesk.core.rbac.user;
import java.util.Optional;
-import java.util.Set;
-
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
@@ -35,17 +33,18 @@ import com.bytedesk.core.constant.UserConsts;
import com.bytedesk.core.exception.EmailExistsException;
import com.bytedesk.core.exception.MobileExistsException;
import com.bytedesk.core.exception.NotFoundException;
+import com.bytedesk.core.rbac.organization.Organization;
+import com.bytedesk.core.rbac.organization.OrganizationRepository;
import com.bytedesk.core.rbac.role.Role;
import com.bytedesk.core.rbac.role.RoleService;
import com.bytedesk.core.uid.UidUtils;
+import com.bytedesk.core.utils.ConvertUtils;
import lombok.AllArgsConstructor;
// import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
-import java.util.HashSet;
-
// @Slf4j
@Service
@AllArgsConstructor
@@ -60,68 +59,61 @@ public class UserService {
private final RoleService roleService;
- private final BytedeskProperties properties;
+ private final BytedeskProperties bytedeskProperties;
private final BCryptPasswordEncoder passwordEncoder;
private final UidUtils uidUtils;
- // public Page query(UserRequest userRequest) {
-
- // Pageable pageable = PageRequest.of(userRequest.getPageNumber(), userRequest.getPageSize(), Sort.Direction.ASC,
- // "updatedAt");
-
- // return userRepository.findAll(pageable);
- // }
+ private final OrganizationRepository organizationRepository;
@Transactional
public UserResponse register(UserRequest userRequest) {
- if (existsByEmailAndPlatform(userRequest.getEmail(), userRequest.getPlatform())) {
+ if (StringUtils.hasText(userRequest.getEmail()) && existsByEmailAndPlatform(userRequest.getEmail(), userRequest.getPlatform())) {
throw new EmailExistsException("Email already exists..!!");
}
- if (existsByMobileAndPlatform(userRequest.getMobile(), userRequest.getPlatform())) {
+ if (StringUtils.hasText(userRequest.getMobile()) && existsByMobileAndPlatform(userRequest.getMobile(), userRequest.getPlatform())) {
throw new MobileExistsException("Mobile already exists..!!");
}
//
User user = modelMapper.map(userRequest, User.class);
user.setUid(uidUtils.getCacheSerialUid());
//
- if (StringUtils.hasLength(userRequest.getNickname())) {
+ if (StringUtils.hasText(userRequest.getNickname())) {
user.setNickname(userRequest.getNickname());
} else {
user.setNickname(createNickname());
}
//
- if (StringUtils.hasLength(userRequest.getAvatar())) {
+ if (StringUtils.hasText(userRequest.getAvatar())) {
user.setAvatar(userRequest.getAvatar());
} else {
user.setAvatar(AvatarConsts.DEFAULT_AVATAR_URL);
}
//
- if (StringUtils.hasLength(userRequest.getPassword())) {
+ if (StringUtils.hasText(userRequest.getPassword())) {
String rawPassword = userRequest.getPassword();
String encodedPassword = passwordEncoder.encode(rawPassword);
user.setPassword(encodedPassword);
}
// 只有经过验证的邮箱,才真正执行注册
- if (StringUtils.hasLength(userRequest.getEmail())) {
+ if (StringUtils.hasText(userRequest.getEmail())) {
user.setUsername(userRequest.getEmail());
user.setNum(userRequest.getEmail());
user.setEmailVerified(true);
- user.setEnabled(true);
}
// 只有经过验证的手机号,才真正执行注册
- if (StringUtils.hasLength(userRequest.getMobile())) {
+ if (StringUtils.hasText(userRequest.getMobile())) {
user.setNum(userRequest.getMobile());
user.setMobileVerified(true);
- user.setEnabled(true);
}
+ user.setEnabled(true);
// TODO: 设置角色role
//
-
+ user = save(user);
//
- return convertToUserResponse(save(user));
+ return ConvertUtils.convertToUserResponse(user);
}
@Transactional
@@ -131,76 +123,94 @@ public class UserService {
if (userOptional.isPresent()) {
User user = userOptional.get();
- if (StringUtils.hasLength(userRequest.getNickname())) {
+ if (StringUtils.hasText(userRequest.getNickname())) {
user.setNickname(userRequest.getNickname());
}
- if (StringUtils.hasLength(userRequest.getAvatar())) {
+ if (StringUtils.hasText(userRequest.getAvatar())) {
user.setAvatar(userRequest.getAvatar());
}
- if (StringUtils.hasLength(userRequest.getPassword())) {
+ if (StringUtils.hasText(userRequest.getPassword())) {
String rawPassword = userRequest.getPassword();
String encodedPassword = passwordEncoder.encode(rawPassword);
user.setPassword(encodedPassword);
}
- if (StringUtils.hasLength(userRequest.getEmail())) {
+ if (StringUtils.hasText(userRequest.getEmail())) {
user.setEmail(userRequest.getEmail());
}
- if (StringUtils.hasLength(userRequest.getMobile())) {
+ if (StringUtils.hasText(userRequest.getMobile())) {
user.setMobile(userRequest.getMobile());
}
- if (StringUtils.hasLength(userRequest.getDescription())) {
+ if (StringUtils.hasText(userRequest.getDescription())) {
user.setDescription(userRequest.getDescription());
}
// TODO: 设置角色role
- return convertToUserResponse(save(user));
+ user = save(user);
+
+ return ConvertUtils.convertToUserResponse(user);
} else {
throw new NotFoundException("User not found..!!");
}
}
+ // String nickname, String avatar, String password, String mobile, String email,
+ // String platform, String orgUid
@Transactional
- public User createUser(String nickname, String avatar, String password, String mobile, String email,
- boolean isVerified, String platform, String orgUid) {
-
+ public User createUser(UserRequest userRequest) {
+ //
+ if (existsByEmailAndPlatform(userRequest.getEmail(), userRequest.getPlatform())) {
+ throw new EmailExistsException("Email already exists..!!");
+ }
+ if (existsByMobileAndPlatform(userRequest.getMobile(), userRequest.getPlatform())) {
+ throw new MobileExistsException("Mobile already exists..!!");
+ }
+ //
User user = User.builder()
- // .uid(uidUtils.getCacheSerialUid())
- .avatar(avatar)
+ // .avatar(userRequest.getAvatar())
// use email as default username
- .username(email)
- .nickname(nickname)
- .mobile(mobile)
- .num(mobile)
- .email(email)
+ .username(userRequest.getEmail())
+ // .nickname(userRequest.getNickname())
+ .mobile(userRequest.getMobile())
+ .num(userRequest.getMobile())
+ .email(userRequest.getEmail())
.superUser(false)
- .emailVerified(isVerified)
- .mobileVerified(isVerified)
- .password(platform)
+ .emailVerified(false)
+ .mobileVerified(false)
+ .password(userRequest.getPlatform())
.build();
user.setUid(uidUtils.getCacheSerialUid());
-
- if (StringUtils.hasLength(password)) {
- user.setPassword(passwordEncoder.encode(password));
+ user.setNickname(userRequest.getNickname());
+ user.setAvatar(userRequest.getAvatar());
+ //
+ if (StringUtils.hasText(userRequest.getPassword())) {
+ user.setPassword(passwordEncoder.encode(userRequest.getPassword()));
} else {
- user.setPassword(passwordEncoder.encode("123456"));
+ user.setPassword(passwordEncoder.encode(bytedeskProperties.getPasswordDefault()));
+ }
+ // user.getOrganizations().add(userRequest.getOrgUid());
+
+ Optional orgOptional = organizationRepository.findByUid(UserConsts.DEFAULT_ORGANIZATION_UID);
+ Optional roleOptional = roleService.findByNameAndOrgUid(TypeConsts.ROLE_CUSTOMER_SERVICE, UserConsts.DEFAULT_ORGANIZATION_UID);
+ if (orgOptional.isPresent() && roleOptional.isPresent()) {
+ Organization organization = orgOptional.get();
+ Role role = roleOptional.get();
+ //
+ user.addOrganizationRole(organization, role);
}
- user.getOrganizations().add(orgUid);
-
return save(user);
- // return user;
}
public User updateUser(User user, String password, String mobile, String email) {
- if (StringUtils.hasLength(password)) {
+ if (StringUtils.hasText(password)) {
user.setPassword(passwordEncoder.encode(password));
}
@@ -213,17 +223,17 @@ public class UserService {
@Cacheable(value = "user", key = "#email", unless = "#result == null")
public Optional findByEmailAndPlatform(String email, String platform) {
- return userRepository.findByEmailAndPlatform(email, platform);
+ return userRepository.findByEmailAndPlatformAndDeleted(email, platform, false);
}
@Cacheable(value = "user", key = "#mobile", unless = "#result == null")
public Optional findByMobileAndPlatform(String mobile, String platform) {
- return userRepository.findByMobileAndPlatform(mobile, platform);
+ return userRepository.findByMobileAndPlatformAndDeleted(mobile, platform, false);
}
@Cacheable(value = "user", key = "#username", unless = "#result == null")
public Optional findByUsernameAndPlatform(String username, String platform) {
- return userRepository.findByUsernameAndPlatform(username, platform);
+ return userRepository.findByUsernameAndPlatformAndDeleted(username, platform, false);
}
@Cacheable(value = "user", key = "#uid", unless = "#result == null")
@@ -233,7 +243,7 @@ public class UserService {
@Cacheable(value = "admin", unless = "#result == null")
public Optional getAdmin() {
- return userRepository.findByUsernameAndPlatform(properties.getUsername(), BdConstants.PLATFORM_BYTEDESK);
+ return userRepository.findByUsernameAndPlatformAndDeleted(bytedeskProperties.getEmail(), BdConstants.PLATFORM_BYTEDESK, false);
}
//
@@ -253,10 +263,10 @@ public class UserService {
}
@Caching(put = {
- @CachePut(value = "user", key = "#user.username"),
- @CachePut(value = "user", key = "#user.mobile"),
- @CachePut(value = "user", key = "#user.email"),
- @CachePut(value = "user", key = "#user.uid"),
+ @CachePut(value = "user", key = "#user.username", unless = "#user.username == null"),
+ @CachePut(value = "user", key = "#user.mobile", unless = "#user.mobile == null"),
+ @CachePut(value = "user", key = "#user.email", unless = "#user.email == null"),
+ @CachePut(value = "user", key = "#user.uid", unless = "#user.uid == null"),
// TODO: 此处put的exists内容跟缓存时内容类型是否一致?
// @CachePut(value = "userExists", key = "#user.username"),
// @CachePut(value = "userExists", key = "#user.mobile"),
@@ -279,14 +289,6 @@ public class UserService {
userRepository.delete(user);
}
- public UserResponse convertToUserResponse(User user) {
- return modelMapper.map(user, UserResponse.class);
- }
-
- public UserResponseSimple convertToUserResponseSimple(User user) {
- return modelMapper.map(user, UserResponseSimple.class);
- }
-
// TODO: 待完善
public String createNickname() {
String randomId = uidUtils.getCacheSerialUid().substring(11, 15);
@@ -295,33 +297,51 @@ public class UserService {
public void initData() {
- if (userRepository.count() > 0) {
+ if (existsByMobileAndPlatform(bytedeskProperties.getMobile(), BdConstants.PLATFORM_BYTEDESK)) {
return;
}
User admin = User.builder()
// .uid(uidUtils.getCacheSerialUid())
- .email(properties.getEmail())
- .username(properties.getUsername())
- .password(new BCryptPasswordEncoder().encode(properties.getPassword()))
- .nickname(properties.getNickname())
- .avatar(AvatarConsts.DEFAULT_AVATAR_URL)
- .mobile(properties.getMobile())
- .num(properties.getMobile())
+ .email(bytedeskProperties.getEmail())
+ .username(bytedeskProperties.getEmail())
+ .password(new BCryptPasswordEncoder().encode(bytedeskProperties.getPassword()))
+ // .nickname(bytedeskProperties.getNickname())
+ // .avatar(AvatarConsts.DEFAULT_AVATAR_URL)
+ .mobile(bytedeskProperties.getMobile())
+ .num(bytedeskProperties.getMobile())
.superUser(true)
.emailVerified(true)
.mobileVerified(true)
.build();
admin.setUid(uidUtils.getCacheSerialUid());
- admin.getOrganizations().add(UserConsts.DEFAULT_ORGANIZATION_UID);
-
- Optional roleOptional = roleService.findByName(TypeConsts.ROLE_SUPER);
- Set roles = new HashSet<>();
- roleOptional.ifPresent(role -> {
- roles.add(role);
- });
- admin.setRoles(roles);
+ admin.setNickname(bytedeskProperties.getNickname());
+ admin.setAvatar(AvatarConsts.DEFAULT_AVATAR_URL);
+ // admin.getOrganizations().add(UserConsts.DEFAULT_ORGANIZATION_UID);
+
+ // Optional roleOptional = roleService.findByName(TypeConsts.ROLE_SUPER);
+ // Set roles = new HashSet<>();
+ // roleOptional.ifPresent(role -> {
+ // roles.add(role);
+ // });
+ // admin.setRoles(roles);
+ //
save(admin);
}
+ public void updateInitData() {
+
+ Optional orgOptional = organizationRepository.findByUid(UserConsts.DEFAULT_ORGANIZATION_UID);
+ Optional roleOptional = roleService.findByNameAndOrgUid(TypeConsts.ROLE_SUPER, UserConsts.DEFAULT_ORGANIZATION_UID);
+ Optional