1
0
mirror of https://github.com/chatopera/cosin.git synced 2025-07-16 00:22:22 +08:00
Signed-off-by: Hai Liang Wang <hai@chatopera.com>
This commit is contained in:
Hai Liang Wang 2023-09-18 15:49:52 +08:00
parent e69dfd398d
commit 629abe88d2
15 changed files with 718 additions and 455 deletions

View File

@ -88,6 +88,7 @@
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.1.3</version>
<executions>
<execution>
<goals>

View File

@ -217,4 +217,13 @@ public class Constants {
public static final String AUTH_TOKEN_TYPE_BEARER = "Bearer";
public static final String AUTH_TOKEN_TYPE_BASIC = "Basic";
/**
* License
*/
public static final String LICENSE_SERVER_INST_ID = "SERVERINSTID";
public static final String LICENSE_SERVICE_NAME = "SERVICENAME";
public static final String LICENSE_SERVICE_NAME_PREFIX = "春松客服";
public static final String LICENSES = "LICENSES";
public static final String METAKV_DATATYPE_STRING = "string";
}

View File

@ -24,6 +24,7 @@ import com.cskefu.cc.model.BlackEntity;
import com.cskefu.cc.model.SysDic;
import com.cskefu.cc.model.SystemConfig;
import com.cskefu.cc.persistence.repository.*;
import com.cskefu.cc.proxy.LicenseProxy;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -36,7 +37,6 @@ public class AppCtxRefreshEventListener implements ApplicationListener<ContextRe
private static final Logger logger = LoggerFactory.getLogger(AppCtxRefreshEventListener.class);
private void setupSysdicCacheAndExtras(final ContextRefreshedEvent event, final String cacheSetupStrategy, final Cache cache, final SysDicRepository sysDicRes, final BlackListRepository blackListRes) {
if (!StringUtils.equalsIgnoreCase(cacheSetupStrategy, Constants.cache_setup_strategy_skip)) {
@ -138,6 +138,9 @@ public class AppCtxRefreshEventListener implements ApplicationListener<ContextRe
logger.info("[Plugins] registered plugin id {}, class {}", p.getPluginId(), p.getClass().getName());
}
// 初始化 ServerInstId
LicenseProxy licenseProxy = event.getApplicationContext().getBean(LicenseProxy.class);
licenseProxy.checkOnStartup();
} else {
logger.info("[onApplicationEvent] bypass, initialization has been done already.");
}

View File

@ -41,7 +41,7 @@ import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;

View File

@ -31,7 +31,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

View File

@ -31,7 +31,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

View File

@ -0,0 +1,77 @@
package com.cskefu.cc.model;
import jakarta.persistence.*;
import java.util.Date;
/**
* 存储元数据
*/
@Entity
@Table(name = "cs_metakv")
@org.hibernate.annotations.Proxy(lazy = false)
public class Metakv implements java.io.Serializable {
@Id
private String metakey;
private String metavalue;
private String datatype;
private String comment;
@Temporal(TemporalType.TIMESTAMP)
private Date updatetime;
@Temporal(TemporalType.TIMESTAMP)
private Date createtime;
public String getMetakey() {
return metakey;
}
public void setMetakey(String metakey) {
this.metakey = metakey;
}
public String getMetavalue() {
return metavalue;
}
public void setMetavalue(String metavalue) {
this.metavalue = metavalue;
}
public String getDatatype() {
return datatype;
}
public void setDatatype(String datatype) {
this.datatype = datatype;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public Date getUpdatetime() {
return updatetime;
}
public void setUpdatetime(Date updatetime) {
this.updatetime = updatetime;
}
public Date getCreatetime() {
return createtime;
}
public void setCreatetime(Date createtime) {
this.createtime = createtime;
}
}

View File

@ -0,0 +1,22 @@
/*
* Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd.
* <https://www.chatopera.com>, Licensed under the Chunsong Public
* License, Version 1.0 (the "License"), https://docs.cskefu.com/licenses/v1.html
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cskefu.cc.persistence.repository;
import com.cskefu.cc.model.Metakv;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface MetakvRepository extends JpaRepository<Metakv, String> {
Optional<Metakv> findFirstByMetakey(final String p1);
}

View File

@ -0,0 +1,93 @@
/*
* Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd.
* <https://www.chatopera.com>, Licensed under the Chunsong Public
* License, Version 1.0 (the "License"), https://docs.cskefu.com/licenses/v1.html
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cskefu.cc.proxy;
import com.cskefu.cc.basic.Constants;
import com.cskefu.cc.basic.MainUtils;
import com.cskefu.cc.model.Metakv;
import com.cskefu.cc.persistence.repository.MetakvRepository;
import com.cskefu.cc.util.Base62;
import org.json.JSONArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.Optional;
@Service
public class LicenseProxy {
private final static Logger logger = LoggerFactory.getLogger(LicenseProxy.class);
@Autowired
private MetakvRepository metkvRes;
/**
* 初始化 serverinstId
* serverinstId 作为服务唯一的实例ID
*/
public void checkOnStartup() {
Optional<Metakv> metaServerinstIdOpt = metkvRes.findFirstByMetakey(Constants.LICENSE_SERVER_INST_ID);
if (metaServerinstIdOpt.isEmpty()) {
// 没有 serverinstId 信息初始化
final String serverinstId = MainUtils.getUUID();
createMetakv(Constants.LICENSE_SERVER_INST_ID, serverinstId, Constants.METAKV_DATATYPE_STRING);
}
Optional<Metakv> metaServicenameOpt = metkvRes.findFirstByMetakey(Constants.LICENSE_SERVICE_NAME);
if (metaServicenameOpt.isEmpty()) {
// 没有 Service Name 信息初始化
final String serviceName = generateLicenseServiceName();
createMetakv(Constants.LICENSE_SERVICE_NAME, serviceName, Constants.METAKV_DATATYPE_STRING);
}
Optional<Metakv> metaLicensesOpt = metkvRes.findFirstByMetakey(Constants.LICENSES);
if (metaLicensesOpt.isEmpty()) {
// 没有 license 信息初始化
createMetakv(Constants.LICENSES, (new JSONArray()).toString(), Constants.METAKV_DATATYPE_STRING);
}
}
/**
* 建立 Metakv 数据
*
* @param key
* @param value
* @param datatype
*/
public void createMetakv(final String key, final String value, final String datatype) {
Date now = new Date();
Metakv metakv = new Metakv();
metakv.setCreatetime(now);
metakv.setUpdatetime(now);
metakv.setMetakey(key);
metakv.setMetavalue(value);
metakv.setDatatype(datatype);
metkvRes.save(metakv);
}
/**
* 生成随机字符串作为服务名称
*
* @return
*/
private String generateLicenseServiceName() {
StringBuffer sb = new StringBuffer();
sb.append(Constants.LICENSE_SERVICE_NAME_PREFIX);
sb.append(Base62.generatingRandomAlphanumericString(5));
return sb.toString();
}
}

View File

@ -17,27 +17,29 @@ package com.cskefu.cc.util;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.Random;
public class Base62 {
private static final int BINARY = 0x2;
private static final int NUMBER_61 = 0x0000003d;
static final char[] DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B',
'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z' };
'X', 'Y', 'Z'};
public static String encode(long value){
return encode(String.valueOf(value)).toLowerCase() ;
public static String encode(long value) {
return encode(String.valueOf(value)).toLowerCase();
}
public static String encode(String str){
public static String encode(String str) {
String md5Hex = DigestUtils.md5Hex(str);
// 6 digit binary can indicate 62 letter & number from 0-9a-zA-Z
int binaryLength = 6 * 6;
long binaryLengthFixer = Long.valueOf(StringUtils.repeat("1", binaryLength), BINARY);
for (int i = 0; i < 4;) {
for (int i = 0; i < 4; ) {
String subString = StringUtils.substring(md5Hex, i * 8, (i + 1) * 8);
subString = Long.toBinaryString(Long.valueOf(subString, 16) & binaryLengthFixer);
subString = StringUtils.leftPad(subString, binaryLength, "0");
@ -48,7 +50,7 @@ public class Base62 {
sbBuilder.append(DIGITS[charIndex]);
}
String shortUrl = sbBuilder.toString();
if(shortUrl!=null){
if (shortUrl != null) {
return shortUrl;
}
}
@ -57,7 +59,26 @@ public class Base62 {
}
@SuppressWarnings("unused")
private static void print(Object messagr){
private static void print(Object messagr) {
System.out.println(messagr);
}
/**
* 生成随机字符串
* @param targetStringLength
* @return
*/
public static String generatingRandomAlphanumericString(final int targetStringLength) {
int leftLimit = 48; // numeral '0'
int rightLimit = 122; // letter 'z'
Random random = new Random();
String generatedString = random.ints(leftLimit, rightLimit + 1)
.filter(i -> (i <= 57 || i >= 65) && (i <= 90 || i >= 97))
.limit(targetStringLength)
.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
.toString();
return generatedString;
}
}

View File

@ -138,6 +138,24 @@ CREATE TABLE `cs_fb_otn_follow` (
-- Records of cs_fb_otn_follow
-- ----------------------------
-- ----------------------------
-- Table structure for cs_metakv
-- ----------------------------
DROP TABLE IF EXISTS `cs_metakv`;
CREATE TABLE `cs_metakv` (
`metakey` varchar(512) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '元数据字段名,唯一标识',
`metavalue` text COLLATE utf8mb4_unicode_ci COMMENT '元数据值',
`createtime` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updatetime` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`datatype` varchar(256) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'string' COMMENT '数据类型',
`comment` varchar(1024) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '字段备注描述',
PRIMARY KEY (`metakey`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统内置元数据';
-- ----------------------------
-- Records of cs_metakv
-- ----------------------------
-- ----------------------------
-- Table structure for cs_organ_user
-- ----------------------------

View File

@ -0,0 +1,14 @@
USE `cosinee`;
-- -----------------
-- prepare variables
-- -----------------
CREATE TABLE IF NOT EXISTS `cs_metakey` (
`metakey` varchar(512) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '元数据字段名,唯一标识',
`metavalue` text COLLATE utf8mb4_unicode_ci COMMENT '元数据值',
`createtime` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updatetime` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`datatype` varchar(256) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'string' COMMENT '数据类型',
`comment` varchar(1024) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '字段备注描述',
PRIMARY KEY (`metakey`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统内置元数据';

View File

@ -400,12 +400,19 @@
<artifactId>compose4j</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.chatopera.bot</groupId>
<artifactId>sdk</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>com.chatopera.store</groupId>
<artifactId>store-sdk</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- Required for Java 11 https://github.com/cskefu/cskefu/issues/714 -->
<dependency>
<groupId>javax.xml.bind</groupId>