From 4c844574758868ec6a96df530171cb92654c033b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=98=95?= Date: Wed, 6 Mar 2024 18:17:09 +0800 Subject: [PATCH] =?UTF-8?q?1.=20=E5=A4=87=E4=BB=BD=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/application-local.yml | 2 +- cs-base/pom.xml | 10 +- .../annotation/OperationLogAnnotation.java | 38 +++ .../cf/cs/base/config}/CacheConfigure.java | 2 +- .../cf/cs/base/config}/CommonConfigure.java | 2 +- .../com/cf/cs/base/misc/ApiContextUtils.java | 62 ++++ .../com/cf/cs/base/pojo/po/ApiContext.java | 24 ++ .../crypto/annotation/DecryptionProtocol.java | 16 + .../crypto/annotation/EncryptionProtocol.java | 16 + cs-database/pom.xml | 75 +++++ .../cf/cs/database/CsDatabaseApplication.java | 23 ++ .../database/common/DataBaseEnumHandler.java | 81 +++++ .../database/config/MybatisFlexConfigure.java | 40 +++ .../cs/database/config/UuidKeyGenerator.java | 14 + .../cf/cs/database/mapper/DictDataMapper.java | 17 + .../cf/cs/database/mapper/DictTypeMapper.java | 17 + .../database/mapper/OperationLogMapper.java | 17 + .../database/mapper/ResourceDataMapper.java | 15 + .../database/mapper/ResourceTypeMapper.java | 17 + .../com/cf/cs/database/mapper/RoleMapper.java | 16 + .../database/mapper/RoleResourceMapper.java | 15 + .../database/mapper/UserCredentialMapper.java | 17 + .../com/cf/cs/database/mapper/UserMapper.java | 27 ++ .../cf/cs/database/pojo/entity/DictData.java | 121 +++++++ .../cf/cs/database/pojo/entity/DictType.java | 88 +++++ .../cs/database/pojo/entity/OperationLog.java | 138 ++++++++ .../cs/database/pojo/entity/ResourceData.java | 62 ++++ .../cs/database/pojo/entity/ResourceType.java | 35 ++ .../com/cf/cs/database/pojo/entity/Role.java | 49 +++ .../cs/database/pojo/entity/RoleResource.java | 46 +++ .../com/cf/cs/database/pojo/entity/User.java | 66 ++++ .../database/pojo/entity/UserCredential.java | 75 +++++ .../database/pojo/po/OperationLogDetails.java | 31 ++ .../database/pojo/po/OperationLogSummary.java | 54 ++++ .../cf/cs/database/pojo/po/PageResults.java | 22 ++ .../cf/cs/database/pojo/po/ResPermInfo.java | 34 ++ .../com/cf/cs/database/pojo/po/UserInfo.java | 38 +++ .../service/OperationLogDataBaseService.java | 79 +++++ .../database/service/UserDataBaseService.java | 39 +++ .../impl/OperationLogDataBaseServiceImpl.java | 252 +++++++++++++++ .../service/impl/UserDataBaseServiceImpl.java | 306 ++++++++++++++++++ .../main/resources/rbac/clean_database.sql | 15 + cs-database/src/main/resources/rbac/data.sql | 212 ++++++++++++ .../src/main/resources/rbac/schema.sql | 220 +++++++++++++ .../database/CsDatabaseApplicationTests.java | 13 + cs-protocol/pom.xml | 43 +++ .../cf/cs/protocol/CsProtocolApplication.java | 23 ++ .../cs/protocol/config/ProtocolConfigure.java | 56 ++++ .../cs/protocol/pojo/base/BaseProtocol.java | 46 +++ .../cs/protocol/pojo/po/BaseRespStatus.java | 19 ++ .../cf/cs/protocol/pojo/po/VersionInfo.java | 24 ++ .../cf/cs/protocol/pojo/vo/ProtocolResp.java | 90 ++++++ .../cf/cs/protocol/pojo/vo/VersionResp.java | 25 ++ .../validation/group/JsonViewGroups.java | 29 ++ .../validation/group/ValidGroups.java | 105 ++++++ .../cs/protocol/validation/valids/UUID.java | 42 +++ .../validation/valids/ValidHttpMethod.java | 43 +++ .../validation/valids/ValidPageSize.java | 43 +++ .../valids/ValidProtocolTimestamp.java | 43 +++ .../valids/impl/ValidHttpMethodImpl.java | 41 +++ .../valids/impl/ValidPageSizeImpl.java | 22 ++ .../impl/ValidProtocolTimestampImpl.java | 55 ++++ .../protocol/CsProtocolApplicationTests.java | 13 + cs-restful/pom.xml | 35 +- .../cf/cs/restful/CsRestfulApplication.java | 3 +- .../controller/CommonFrameworkApi.java | 62 ++++ cs-services/pom.xml | 38 +++ .../cf/cs/services/CsServicesApplication.java | 23 ++ .../services/CsServicesApplicationTests.java | 13 + cs-web/pom.xml | 10 +- .../interceptor/RequestBodyCacheWrapper.java | 109 +++++++ .../cs/web/interceptor/RequestBodyFilter.java | 45 +++ .../com/cf/cs/web/setup/SystemInitial.java | 2 +- pom.xml | 3 + 74 files changed, 3648 insertions(+), 15 deletions(-) create mode 100644 cs-base/src/main/java/com/cf/cs/base/annotation/OperationLogAnnotation.java rename {cs-web/src/main/java/com/cf/cs/web/configure => cs-base/src/main/java/com/cf/cs/base/config}/CacheConfigure.java (98%) rename {cs-web/src/main/java/com/cf/cs/web/configure => cs-base/src/main/java/com/cf/cs/base/config}/CommonConfigure.java (98%) create mode 100644 cs-base/src/main/java/com/cf/cs/base/misc/ApiContextUtils.java create mode 100644 cs-base/src/main/java/com/cf/cs/base/pojo/po/ApiContext.java create mode 100644 cs-crypto/src/main/java/com/cf/cs/crypto/annotation/DecryptionProtocol.java create mode 100644 cs-crypto/src/main/java/com/cf/cs/crypto/annotation/EncryptionProtocol.java create mode 100644 cs-database/pom.xml create mode 100644 cs-database/src/main/java/com/cf/cs/database/CsDatabaseApplication.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/common/DataBaseEnumHandler.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/config/MybatisFlexConfigure.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/config/UuidKeyGenerator.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/mapper/DictDataMapper.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/mapper/DictTypeMapper.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/mapper/OperationLogMapper.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/mapper/ResourceDataMapper.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/mapper/ResourceTypeMapper.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/mapper/RoleMapper.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/mapper/RoleResourceMapper.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/mapper/UserCredentialMapper.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/mapper/UserMapper.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/pojo/entity/DictData.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/pojo/entity/DictType.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/pojo/entity/OperationLog.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/pojo/entity/ResourceData.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/pojo/entity/ResourceType.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/pojo/entity/Role.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/pojo/entity/RoleResource.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/pojo/entity/User.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/pojo/entity/UserCredential.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/pojo/po/OperationLogDetails.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/pojo/po/OperationLogSummary.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/pojo/po/PageResults.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/pojo/po/ResPermInfo.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/pojo/po/UserInfo.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/service/OperationLogDataBaseService.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/service/UserDataBaseService.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/service/impl/OperationLogDataBaseServiceImpl.java create mode 100644 cs-database/src/main/java/com/cf/cs/database/service/impl/UserDataBaseServiceImpl.java create mode 100644 cs-database/src/main/resources/rbac/clean_database.sql create mode 100644 cs-database/src/main/resources/rbac/data.sql create mode 100644 cs-database/src/main/resources/rbac/schema.sql create mode 100644 cs-database/src/test/java/com/cf/cs/database/CsDatabaseApplicationTests.java create mode 100644 cs-protocol/pom.xml create mode 100644 cs-protocol/src/main/java/com/cf/cs/protocol/CsProtocolApplication.java create mode 100644 cs-protocol/src/main/java/com/cf/cs/protocol/config/ProtocolConfigure.java create mode 100644 cs-protocol/src/main/java/com/cf/cs/protocol/pojo/base/BaseProtocol.java create mode 100644 cs-protocol/src/main/java/com/cf/cs/protocol/pojo/po/BaseRespStatus.java create mode 100644 cs-protocol/src/main/java/com/cf/cs/protocol/pojo/po/VersionInfo.java create mode 100644 cs-protocol/src/main/java/com/cf/cs/protocol/pojo/vo/ProtocolResp.java create mode 100644 cs-protocol/src/main/java/com/cf/cs/protocol/pojo/vo/VersionResp.java create mode 100644 cs-protocol/src/main/java/com/cf/cs/protocol/validation/group/JsonViewGroups.java create mode 100644 cs-protocol/src/main/java/com/cf/cs/protocol/validation/group/ValidGroups.java create mode 100644 cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/UUID.java create mode 100644 cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/ValidHttpMethod.java create mode 100644 cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/ValidPageSize.java create mode 100644 cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/ValidProtocolTimestamp.java create mode 100644 cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/impl/ValidHttpMethodImpl.java create mode 100644 cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/impl/ValidPageSizeImpl.java create mode 100644 cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/impl/ValidProtocolTimestampImpl.java create mode 100644 cs-protocol/src/test/java/com/cf/cs/protocol/CsProtocolApplicationTests.java create mode 100644 cs-restful/src/main/java/com/cf/cs/restful/controller/CommonFrameworkApi.java create mode 100644 cs-services/pom.xml create mode 100644 cs-services/src/main/java/com/cf/cs/services/CsServicesApplication.java create mode 100644 cs-services/src/test/java/com/cf/cs/services/CsServicesApplicationTests.java create mode 100644 cs-web/src/main/java/com/cf/cs/web/interceptor/RequestBodyCacheWrapper.java create mode 100644 cs-web/src/main/java/com/cf/cs/web/interceptor/RequestBodyFilter.java diff --git a/config/application-local.yml b/config/application-local.yml index 8de3de0..621bc04 100644 --- a/config/application-local.yml +++ b/config/application-local.yml @@ -66,7 +66,7 @@ mybatis : mapper-locations : classpath*:mappers/*.xml type-aliases-package: com.cmhi.gds.pojo.entry configuration : - default-enum-type-handler: com.cmhi.cf.common.CommonEnumHandler + default-enum-type-handler: com.cf.cs.database.common.DataBaseEnumHandler mybatis-flex: global-config: diff --git a/cs-base/pom.xml b/cs-base/pom.xml index 0a3bc83..84b7d63 100644 --- a/cs-base/pom.xml +++ b/cs-base/pom.xml @@ -27,7 +27,16 @@ spring-boot-starter-test test + + org.springframework.boot + spring-boot-starter-cache + + + com.github.ben-manes.caffeine + caffeine + 3.1.8 + com.houkunlin system-dict-starter @@ -40,7 +49,6 @@ 23.0.0 - diff --git a/cs-base/src/main/java/com/cf/cs/base/annotation/OperationLogAnnotation.java b/cs-base/src/main/java/com/cf/cs/base/annotation/OperationLogAnnotation.java new file mode 100644 index 0000000..6a3951e --- /dev/null +++ b/cs-base/src/main/java/com/cf/cs/base/annotation/OperationLogAnnotation.java @@ -0,0 +1,38 @@ +package com.cf.cs.base.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * The interface Operation log annotation. + * + * @author xajhuang @163.com + */ +@Target({ElementType.PARAMETER, ElementType.METHOD}) // 注解放置的目标位置,PARAMETER: 可用在参数上 METHOD:可用在方法级别上 +@Retention(RetentionPolicy.RUNTIME) // 指明修饰的注解的生存周期 RUNTIME:运行级别保留 +@Documented +public @interface OperationLogAnnotation { + /** + * Operation module string. + * + * @return the string + */ + String OperationModule() default ""; // 操作模块 + + /** + * Operation type string. + * + * @return the string + */ + String OperationType() default ""; // 操作类型 + + /** + * Operation desc string. + * + * @return the string + */ + String OperationDesc() default ""; // 操作说明 +} diff --git a/cs-web/src/main/java/com/cf/cs/web/configure/CacheConfigure.java b/cs-base/src/main/java/com/cf/cs/base/config/CacheConfigure.java similarity index 98% rename from cs-web/src/main/java/com/cf/cs/web/configure/CacheConfigure.java rename to cs-base/src/main/java/com/cf/cs/base/config/CacheConfigure.java index e5ed27d..6f251d1 100644 --- a/cs-web/src/main/java/com/cf/cs/web/configure/CacheConfigure.java +++ b/cs-base/src/main/java/com/cf/cs/base/config/CacheConfigure.java @@ -1,4 +1,4 @@ -package com.cf.cs.web.configure; +package com.cf.cs.base.config; import com.cf.cs.base.common.CachePool; import com.github.benmanes.caffeine.cache.Caffeine; diff --git a/cs-web/src/main/java/com/cf/cs/web/configure/CommonConfigure.java b/cs-base/src/main/java/com/cf/cs/base/config/CommonConfigure.java similarity index 98% rename from cs-web/src/main/java/com/cf/cs/web/configure/CommonConfigure.java rename to cs-base/src/main/java/com/cf/cs/base/config/CommonConfigure.java index 14f5c2e..319a0e9 100644 --- a/cs-web/src/main/java/com/cf/cs/web/configure/CommonConfigure.java +++ b/cs-base/src/main/java/com/cf/cs/base/config/CommonConfigure.java @@ -1,4 +1,4 @@ -package com.cf.cs.web.configure; +package com.cf.cs.base.config; import jakarta.annotation.PostConstruct; import jakarta.annotation.Resource; diff --git a/cs-base/src/main/java/com/cf/cs/base/misc/ApiContextUtils.java b/cs-base/src/main/java/com/cf/cs/base/misc/ApiContextUtils.java new file mode 100644 index 0000000..db16bc4 --- /dev/null +++ b/cs-base/src/main/java/com/cf/cs/base/misc/ApiContextUtils.java @@ -0,0 +1,62 @@ +package com.cf.cs.base.misc; + + +import com.cf.cs.base.pojo.po.ApiContext; + +/** + * The type Api context utils. + * + * @author xajhuang @163.com + */ +public class ApiContextUtils { + private static final ThreadLocal API_CONTEXT = new ThreadLocal<>(); + + /** + * Get api context. + * + * @return the api context + */ + public static ApiContext get() { + ApiContext context = API_CONTEXT.get(); + if (context == null) { + context = new ApiContext(); + API_CONTEXT.set(context); + } + return context; + } + + /** + * Sets request info. + * + * @param reqBody the req body + * @param reqTime the req time + */ + public static void setRequestInfo(String reqBody, Long reqTime) { + ApiContext context = get(); + context.setRequestBody(reqBody); + context.setRequestTime(reqTime); + } + + /** + * Sets jwt user info. + * + * @param jwt the jwt + * @param username the username + * @param uid the uid + * @param id the id + */ + public static void setJwtUserInfo(String jwt, String username, String uid, Long id) { + ApiContext context = get(); + context.setJwt(jwt); + context.setUsername(username); + context.setUid(uid); + context.setId(id); + } + + /** + * Clear. + */ + public static void clear() { + API_CONTEXT.remove(); + } +} diff --git a/cs-base/src/main/java/com/cf/cs/base/pojo/po/ApiContext.java b/cs-base/src/main/java/com/cf/cs/base/pojo/po/ApiContext.java new file mode 100644 index 0000000..0b03dca --- /dev/null +++ b/cs-base/src/main/java/com/cf/cs/base/pojo/po/ApiContext.java @@ -0,0 +1,24 @@ +package com.cf.cs.base.pojo.po; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * The type Api context. + * + * @author xajhuang @163.com + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ApiContext { + private String requestBody; + private Long requestTime; + private String jwt; + private String username; + private String uid; + private Long id; +} diff --git a/cs-crypto/src/main/java/com/cf/cs/crypto/annotation/DecryptionProtocol.java b/cs-crypto/src/main/java/com/cf/cs/crypto/annotation/DecryptionProtocol.java new file mode 100644 index 0000000..7e07df9 --- /dev/null +++ b/cs-crypto/src/main/java/com/cf/cs/crypto/annotation/DecryptionProtocol.java @@ -0,0 +1,16 @@ +package com.cf.cs.crypto.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * The interface Decryption protocol. + * + * @author xajhuang @163.com + */ +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface DecryptionProtocol { +} diff --git a/cs-crypto/src/main/java/com/cf/cs/crypto/annotation/EncryptionProtocol.java b/cs-crypto/src/main/java/com/cf/cs/crypto/annotation/EncryptionProtocol.java new file mode 100644 index 0000000..e7e9e2e --- /dev/null +++ b/cs-crypto/src/main/java/com/cf/cs/crypto/annotation/EncryptionProtocol.java @@ -0,0 +1,16 @@ +package com.cf.cs.crypto.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * The interface Encryption protocol. + * + * @author xajhuang @163.com + */ +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface EncryptionProtocol { +} diff --git a/cs-database/pom.xml b/cs-database/pom.xml new file mode 100644 index 0000000..72929d7 --- /dev/null +++ b/cs-database/pom.xml @@ -0,0 +1,75 @@ + + + 4.0.0 + + com.cf.cs + IntegrateService + 0.0.1-dev + + + cs-database + cs-database + cs-database + jar + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 3.0.3 + + + org.springframework.security + spring-security-core + 6.2.2 + + + com.mysql + mysql-connector-j + runtime + + + org.springframework.boot + spring-boot-starter-test + test + + + com.zaxxer + HikariCP + + + com.mybatis-flex + mybatis-flex-spring-boot3-starter + 1.7.8 + + + com.mybatis-flex + mybatis-flex-processor + 1.7.8 + provided + + + com.jayway.jsonpath + json-path + 2.9.0 + + + + com.cf.cs + cs-base + ${cs-package.version} + compile + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/cs-database/src/main/java/com/cf/cs/database/CsDatabaseApplication.java b/cs-database/src/main/java/com/cf/cs/database/CsDatabaseApplication.java new file mode 100644 index 0000000..09a38e1 --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/CsDatabaseApplication.java @@ -0,0 +1,23 @@ +package com.cf.cs.database; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * The type Cs database application. + * + * @author xajhuang @163.com + */ +@SpringBootApplication +public class CsDatabaseApplication { + + /** + * The entry point of application. + * + * @param args the input arguments + */ + public static void main(String[] args) { + SpringApplication.run(CsDatabaseApplication.class, args); + } + +} diff --git a/cs-database/src/main/java/com/cf/cs/database/common/DataBaseEnumHandler.java b/cs-database/src/main/java/com/cf/cs/database/common/DataBaseEnumHandler.java new file mode 100644 index 0000000..8cf96b8 --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/common/DataBaseEnumHandler.java @@ -0,0 +1,81 @@ +package com.cf.cs.database.common; + +import com.cf.cs.base.common.BaseEnum; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; + +/** + * The type Data base enum handler. + * + * @param the type parameter + * @author xajhuang @163.com + */ +public class DataBaseEnumHandler extends BaseTypeHandler { + private final Class enumType; + private final List enums; + + /** + * Instantiates a new Data base enum handler. + * + * @param type the type + */ + public DataBaseEnumHandler(Class type) { + if (type == null) { + throw new IllegalArgumentException("Type argument cannot be null"); + } + + this.enumType = type; + this.enums = Arrays.asList(type.getEnumConstants()); + } + + @Override + public void setNonNullParameter(PreparedStatement preparedStatement, int i, E e, JdbcType jdbcType) throws SQLException { + preparedStatement.setInt(i, e.getValue()); + } + + @Override + public E getNullableResult(ResultSet resultSet, String s) throws SQLException { + if (resultSet.getObject(s) == null) { + return null; + } + + int val = resultSet.getInt(s); + return locateEnumStatus(val); + } + + @Override + public E getNullableResult(ResultSet resultSet, int index) throws SQLException { + if (resultSet.getObject(index) == null) { + return null; + } + + int val = resultSet.getInt(index); + return locateEnumStatus(val); + } + + @Override + public E getNullableResult(CallableStatement callableStatement, int index) throws SQLException { + if (callableStatement.getObject(index) == null) { + return null; + } + + int val = callableStatement.getInt(index); + return locateEnumStatus(val); + } + + private E locateEnumStatus(int index) { + for (E e : enums) { + if (e.getValue() == index) { + return e; + } + } + throw new IllegalArgumentException(enumType.getName() + " unknown enumerated type index:" + index); + } +} diff --git a/cs-database/src/main/java/com/cf/cs/database/config/MybatisFlexConfigure.java b/cs-database/src/main/java/com/cf/cs/database/config/MybatisFlexConfigure.java new file mode 100644 index 0000000..e3d405d --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/config/MybatisFlexConfigure.java @@ -0,0 +1,40 @@ +package com.cf.cs.database.config; + +import com.cf.cs.base.config.CommonConfigure; +import com.mybatisflex.core.audit.AuditManager; +import com.mybatisflex.core.audit.ConsoleMessageCollector; +import com.mybatisflex.core.audit.MessageCollector; +import com.mybatisflex.core.keygen.KeyGeneratorFactory; +import com.mybatisflex.core.logicdelete.LogicDeleteProcessor; +import com.mybatisflex.core.logicdelete.impl.DateTimeLogicDeleteProcessor; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@MapperScan(value = {"com.cf.cs.database.mapper"}) +public class MybatisFlexConfigure { + @Resource + private CommonConfigure configure; + + @PostConstruct + private void initGlobalValue() { + KeyGeneratorFactory.register("UUID", new UuidKeyGenerator()); + + if (configure.isShowSqlCommand()) { + //开启审计功能 + AuditManager.setAuditEnable(true); + + //设置 SQL 审计收集器 + MessageCollector collector = new ConsoleMessageCollector(); + AuditManager.setMessageCollector(collector); + } + } + + @Bean + public LogicDeleteProcessor logicDeleteProcessor(){ + return new DateTimeLogicDeleteProcessor(); + } +} diff --git a/cs-database/src/main/java/com/cf/cs/database/config/UuidKeyGenerator.java b/cs-database/src/main/java/com/cf/cs/database/config/UuidKeyGenerator.java new file mode 100644 index 0000000..d221bae --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/config/UuidKeyGenerator.java @@ -0,0 +1,14 @@ +package com.cf.cs.database.config; + +import com.mybatisflex.core.keygen.IKeyGenerator; + +import java.util.UUID; + +public class UuidKeyGenerator implements IKeyGenerator { + public static final String COMMON_UUID = "UUID"; + + @Override + public Object generate(Object entity, String keyColumn) { + return UUID.randomUUID().toString(); + } +} diff --git a/cs-database/src/main/java/com/cf/cs/database/mapper/DictDataMapper.java b/cs-database/src/main/java/com/cf/cs/database/mapper/DictDataMapper.java new file mode 100644 index 0000000..cb0f0f3 --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/mapper/DictDataMapper.java @@ -0,0 +1,17 @@ +package com.cf.cs.database.mapper; + +import com.cf.cs.database.pojo.entity.DictData; +import com.mybatisflex.core.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * 字典数据表 映射层。 + * + * @author mybatis-flex-helper automatic generation + * @since 1.0 + */ +@Mapper +public interface DictDataMapper extends BaseMapper { + + +} diff --git a/cs-database/src/main/java/com/cf/cs/database/mapper/DictTypeMapper.java b/cs-database/src/main/java/com/cf/cs/database/mapper/DictTypeMapper.java new file mode 100644 index 0000000..c1e3ad1 --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/mapper/DictTypeMapper.java @@ -0,0 +1,17 @@ +package com.cf.cs.database.mapper; + +import com.cf.cs.database.pojo.entity.DictType; +import com.mybatisflex.core.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * 字典类型表 映射层。 + * + * @author mybatis-flex-helper automatic generation + * @since 1.0 + */ +@Mapper +public interface DictTypeMapper extends BaseMapper { + + +} diff --git a/cs-database/src/main/java/com/cf/cs/database/mapper/OperationLogMapper.java b/cs-database/src/main/java/com/cf/cs/database/mapper/OperationLogMapper.java new file mode 100644 index 0000000..a531722 --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/mapper/OperationLogMapper.java @@ -0,0 +1,17 @@ +package com.cf.cs.database.mapper; + +import com.cf.cs.database.pojo.entity.OperationLog; +import com.mybatisflex.core.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * 系统操作日志 映射层。 + * + * @author mybatis-flex-helper automatic generation + * @since 1.0 + */ +@Mapper +public interface OperationLogMapper extends BaseMapper { + + +} diff --git a/cs-database/src/main/java/com/cf/cs/database/mapper/ResourceDataMapper.java b/cs-database/src/main/java/com/cf/cs/database/mapper/ResourceDataMapper.java new file mode 100644 index 0000000..f356540 --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/mapper/ResourceDataMapper.java @@ -0,0 +1,15 @@ +package com.cf.cs.database.mapper; + +import com.cf.cs.database.pojo.entity.ResourceData; +import com.mybatisflex.core.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * 映射层。 + * + * @author mybatis-flex-helper automatic generation + * @since 1.0 + */ +@Mapper +public interface ResourceDataMapper extends BaseMapper { +} diff --git a/cs-database/src/main/java/com/cf/cs/database/mapper/ResourceTypeMapper.java b/cs-database/src/main/java/com/cf/cs/database/mapper/ResourceTypeMapper.java new file mode 100644 index 0000000..72546f9 --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/mapper/ResourceTypeMapper.java @@ -0,0 +1,17 @@ +package com.cf.cs.database.mapper; + +import com.cf.cs.database.pojo.entity.ResourceType; +import com.mybatisflex.core.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * 映射层。 + * + * @author mybatis-flex-helper automatic generation + * @since 1.0 + */ +@Mapper +public interface ResourceTypeMapper extends BaseMapper { + + +} diff --git a/cs-database/src/main/java/com/cf/cs/database/mapper/RoleMapper.java b/cs-database/src/main/java/com/cf/cs/database/mapper/RoleMapper.java new file mode 100644 index 0000000..474b899 --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/mapper/RoleMapper.java @@ -0,0 +1,16 @@ +package com.cf.cs.database.mapper; + +import com.cf.cs.database.pojo.entity.Role; +import com.mybatisflex.core.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * 权限 映射层。 + * + * @author mybatis-flex-helper automatic generation + * @since 1.0 + */ +@Mapper +public interface RoleMapper extends BaseMapper { + +} diff --git a/cs-database/src/main/java/com/cf/cs/database/mapper/RoleResourceMapper.java b/cs-database/src/main/java/com/cf/cs/database/mapper/RoleResourceMapper.java new file mode 100644 index 0000000..dcd9eb3 --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/mapper/RoleResourceMapper.java @@ -0,0 +1,15 @@ +package com.cf.cs.database.mapper; + +import com.cf.cs.database.pojo.entity.RoleResource; +import com.mybatisflex.core.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * 权限资源 映射层。 + * + * @author mybatis-flex-helper automatic generation + * @since 1.0 + */ +@Mapper +public interface RoleResourceMapper extends BaseMapper { +} diff --git a/cs-database/src/main/java/com/cf/cs/database/mapper/UserCredentialMapper.java b/cs-database/src/main/java/com/cf/cs/database/mapper/UserCredentialMapper.java new file mode 100644 index 0000000..cba1368 --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/mapper/UserCredentialMapper.java @@ -0,0 +1,17 @@ +package com.cf.cs.database.mapper; + +import com.cf.cs.database.pojo.entity.UserCredential; +import com.mybatisflex.core.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * 用户认证 映射层。 + * + * @author mybatis-flex-helper automatic generation + * @since 1.0 + */ +@Mapper +public interface UserCredentialMapper extends BaseMapper { + + +} diff --git a/cs-database/src/main/java/com/cf/cs/database/mapper/UserMapper.java b/cs-database/src/main/java/com/cf/cs/database/mapper/UserMapper.java new file mode 100644 index 0000000..a75777f --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/mapper/UserMapper.java @@ -0,0 +1,27 @@ +package com.cf.cs.database.mapper; + +import com.cf.cs.database.pojo.entity.User; +import com.mybatisflex.core.BaseMapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 用户表(User)表数据库访问层 + * + * @author makejava + * @since 2023-12-19 17:35:25 + */ +public interface UserMapper extends BaseMapper { + + /** + * 批量新增或按主键更新数据(MyBatis原生foreach方法) + * + * @param entities List 实例对象列表 + * @return 影响行数 + * @throws org.springframework.jdbc.BadSqlGrammarException 入参是空List的时候会抛SQL语句错误的异常,请自行校验入参 + */ + int insertOrUpdateBatch(@Param("entities") List entities); + +} + diff --git a/cs-database/src/main/java/com/cf/cs/database/pojo/entity/DictData.java b/cs-database/src/main/java/com/cf/cs/database/pojo/entity/DictData.java new file mode 100644 index 0000000..3260000 --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/pojo/entity/DictData.java @@ -0,0 +1,121 @@ +package com.cf.cs.database.pojo.entity; + +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.KeyType; +import com.mybatisflex.annotation.Table; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.sql.Timestamp; + +/** + * 字典数据表 实体类。 + * + * @author mybatis -flex-helper automatic generation + * @since 1.0 + */ +@Data +@Schema(name = "字典数据表") +@Table(value = "sys_dict_data") +@AllArgsConstructor +@NoArgsConstructor +public class DictData { + + /** + * 字典编码 + */ + @Schema(description = "字典编码") + @Id(keyType = KeyType.Auto) + private Long id; + + /** + * 字典排序 + */ + @Schema(description = "字典排序") + @Column(value = "dict_sort") + private Integer dictSort; + + /** + * 字典标签 + */ + @Schema(description = "字典标签") + @Column(value = "dict_label") + private String dictLabel; + + /** + * 字典键值 + */ + @Schema(description = "字典键值") + @Column(value = "dict_value") + private Integer dictValue; + + /** + * 字典类型 + */ + @Schema(description = "字典类型") + @Column(value = "type_id") + private Long typeId; + + /** + * 样式属性(其他样式扩展) + */ + @Schema(description = "样式属性(其他样式扩展)") + @Column(value = "css_class") + private String cssClass; + + /** + * 表格回显样式 + */ + @Schema(description = "表格回显样式") + @Column(value = "list_class") + private String listClass; + + /** + * 是否默认(Y是 N否) + */ + @Schema(description = "是否默认(Y是 N否)") + @Column(value = "is_default") + private String isDefault; + + /** + * 创建者 + */ + @Schema(description = "创建者") + @Column(value = "create_by") + private String createBy; + + /** + * 创建时间 + */ + @Schema(description = "创建时间") + @Column(value = "create_time") + private Timestamp createTime; + + /** + * 更新者 + */ + @Schema(description = "更新者") + @Column(value = "update_by") + private String updateBy; + + /** + * 更新时间 + */ + @Schema(description = "更新时间") + @Column(value = "update_time") + private Timestamp updateTime; + + /** + * 备注 + */ + @Schema(description = "备注") + @Column(value = "remark") + private String remark; + + @Schema(description = "逻辑删除标记") + @Column(value = "delete_time", isLogicDelete = true) + private Timestamp deleteTime; +} diff --git a/cs-database/src/main/java/com/cf/cs/database/pojo/entity/DictType.java b/cs-database/src/main/java/com/cf/cs/database/pojo/entity/DictType.java new file mode 100644 index 0000000..b36bee7 --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/pojo/entity/DictType.java @@ -0,0 +1,88 @@ +package com.cf.cs.database.pojo.entity; + +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.KeyType; +import com.mybatisflex.annotation.RelationOneToMany; +import com.mybatisflex.annotation.Table; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.sql.Timestamp; +import java.util.List; + +/** + * 字典类型表 实体类。 + * + * @author mybatis -flex-helper automatic generation + * @since 1.0 + */ +@Data +@Schema(name = "字典类型表") +@Table(value = "sys_dict_type") +public class DictType { + + /** + * 字典主键 + */ + @Schema(description = "字典主键") + @Id(keyType = KeyType.Auto) + private Long id; + + /** + * 字典名称 + */ + @Schema(description = "字典名称") + @Column(value = "dict_name") + private String dictName; + + /** + * 字典类型 + */ + @Schema(description = "字典类型") + @Column(value = "dict_type") + private String dictType; + + /** + * 创建者 + */ + @Schema(description = "创建者") + @Column(value = "create_by") + private String createBy; + + /** + * 创建时间 + */ + @Schema(description = "创建时间") + @Column(value = "create_time") + private Timestamp createTime; + + /** + * 更新者 + */ + @Schema(description = "更新者") + @Column(value = "update_by") + private String updateBy; + + /** + * 更新时间 + */ + @Schema(description = "更新时间") + @Column(value = "update_time") + private Timestamp updateTime; + + /** + * 备注 + */ + @Schema(description = "备注") + @Column(value = "remark") + private String remark; + + @Schema(description = "逻辑删除标记") + @Column(value = "delete_time", isLogicDelete = true) + private Timestamp deleteTime; + + @RelationOneToMany(selfField = "id", targetField = "typeId", targetTable = "sys_dict_data") + @Column(ignore = true) + private List dictDataList; +} diff --git a/cs-database/src/main/java/com/cf/cs/database/pojo/entity/OperationLog.java b/cs-database/src/main/java/com/cf/cs/database/pojo/entity/OperationLog.java new file mode 100644 index 0000000..cc15d0c --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/pojo/entity/OperationLog.java @@ -0,0 +1,138 @@ +package com.cf.cs.database.pojo.entity; + +import com.cf.cs.database.config.UuidKeyGenerator; +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.KeyType; +import com.mybatisflex.annotation.Table; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.sql.Timestamp; + +/** + * 系统操作日志 实体类。 + * + * @author mybatis -flex-helper automatic generation + * @since 1.0 + */ +@Data +@Schema(name = "系统操作日志") +@Table(value = "sys_operation_log") +public class OperationLog { + /** + * id + */ + @Schema(description = "id") + @Id(keyType = KeyType.Auto) + private Long id; + + @Schema(description = "uid") + @Id(keyType = KeyType.Generator, value = UuidKeyGenerator.COMMON_UUID) + private String uid; + + /** + * 操作模块 + */ + @Schema(description = "操作模块") + @Column(value = "module") + private String module; + + /** + * 操作类型 + */ + @Schema(description = "操作类型") + @Column(value = "operation_type") + private String operationType; + + /** + * 操作状态 + */ + @Schema(description = "操作状态") + @Column(value = "operation_status") + private String operationStatus; + + /** + * 操作说明 + */ + @Schema(description = "操作说明") + @Column(value = "description") + private String description; + + /** + * 请求来源 IP 地址 + */ + @Schema(description = "请求来源 IP 地址") + @Column(value = "request_ip") + private String requestIp; + + /** + * 请求接口 + */ + @Schema(description = "请求接口") + @Column(value = "call_function") + private String callFunction; + + /** + * HTTP 请求类型 + */ + @Schema(description = "HTTP 请求类型") + @Column(value = "http_method") + private String httpMethod; + + /** + * 请求URI + */ + @Schema(description = "请求URI") + @Column(value = "http_path") + private String httpPath; + + /** + * 响应时间(ms) + */ + @Schema(description = "响应时间(ms)") + @Column(value = "expend_time") + private Long expendTime; + + /** + * 传输延时(ms) + */ + @Schema(description = "传输延时(ms)") + @Column(value = "transmit_delay") + private Long transmitDelay; + + /** + * 操作用户id + */ + @Schema(description = "操作用户id") + @Column(value = "user_id") + private Long userId; + + /** + * HTTP 请求头所有参数 + */ + @Schema(description = "HTTP 请求头所有参数") + @Column(value = "request_headers") + private String requestHeaders; + + /** + * 操作请求参数 + */ + @Schema(description = "操作请求参数") + @Column(value = "request") + private String request; + + /** + * 操作返回结果 + */ + @Schema(description = "操作返回结果") + @Column(value = "result") + private String result; + + /** + * 操作时间 + */ + @Schema(description = "操作时间") + @Column(value = "operation_time") + private Timestamp operationTime; +} diff --git a/cs-database/src/main/java/com/cf/cs/database/pojo/entity/ResourceData.java b/cs-database/src/main/java/com/cf/cs/database/pojo/entity/ResourceData.java new file mode 100644 index 0000000..5fc6ad0 --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/pojo/entity/ResourceData.java @@ -0,0 +1,62 @@ +package com.cf.cs.database.pojo.entity; + +import com.cf.cs.database.config.UuidKeyGenerator; +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.KeyType; +import com.mybatisflex.annotation.RelationOneToOne; +import com.mybatisflex.annotation.Table; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 实体类。 + * + * @author mybatis -flex-helper automatic generation + * @since 1.0 + */ +@Data +@Schema(name = "$table.comment") +@Table(value = "rbac_resource_data") +public class ResourceData { + + /** + * id + */ + @Schema(description = "id") + @Id(keyType = KeyType.Auto) + private Long id; + + @Schema(description = "uid") + @Id(keyType = KeyType.Generator, value = UuidKeyGenerator.COMMON_UUID) + private String uid; + + /** + * 资源URL + */ + @Schema(description = "资源URL") + @Column(value = "path") + private String path; + + /** + * 资源名称 + */ + @Schema(description = "资源名称") + @Column(value = "name") + private String name; + + /** + * 资源访问 HTTP 方法 GET/POST/DELETE/... + */ + @Schema(description = "资源访问 HTTP 方法 GET/POST/DELETE/...") + @Column(value = "http_method") + private String httpMethod; + + @Schema(description = "资源类型") + @Column(value = "type_id") + private Integer typeId; + + @RelationOneToOne(selfField = "typeId", targetField = "typeId", targetTable = "rbac_resource_type") + @Column(ignore = true) + private ResourceType resType; +} diff --git a/cs-database/src/main/java/com/cf/cs/database/pojo/entity/ResourceType.java b/cs-database/src/main/java/com/cf/cs/database/pojo/entity/ResourceType.java new file mode 100644 index 0000000..e426f2a --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/pojo/entity/ResourceType.java @@ -0,0 +1,35 @@ +package com.cf.cs.database.pojo.entity; + +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.KeyType; +import com.mybatisflex.annotation.Table; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 实体类。 + * + * @author mybatis -flex-helper automatic generation + * @since 1.0 + */ +@Data +@Schema(name = "$table.comment") +@Table(value = "rbac_resource_type") +public class ResourceType { + + /** + * 资源类型:0-->路由,1-->菜单,2-->按钮,... + */ + @Schema(description = "资源类型:0-->路由,1-->菜单,2-->按钮,...") + @Id(keyType = KeyType.Auto) + private Integer typeId; + + /** + * 资源名称 + */ + @Schema(description = "资源名称") + @Column(value = "name") + private String name; + +} diff --git a/cs-database/src/main/java/com/cf/cs/database/pojo/entity/Role.java b/cs-database/src/main/java/com/cf/cs/database/pojo/entity/Role.java new file mode 100644 index 0000000..25e3064 --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/pojo/entity/Role.java @@ -0,0 +1,49 @@ +package com.cf.cs.database.pojo.entity; + +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.KeyType; +import com.mybatisflex.annotation.Table; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 权限(Role)表实体类 + * + * @author makejava @163.com + * @since 2023 -12-19 15:14:43 + */ +@Data +@Schema(name = "Role", description = "权限") +@Table("rbac_role") +@AllArgsConstructor +@NoArgsConstructor +public class Role { + /** + * id + */ + @Schema(description = "id") + @Id(keyType = KeyType.Auto) + private Long id; + /** + * 是否有效 + */ + @Schema(description = "是否有效") + @Column(value = "available") + private Boolean available; + /** + * 权限描述 + */ + @Schema(description = "权限描述") + @Column(value = "description") + private String description; + /** + * 权限名称 + */ + @Schema(description = "权限名称") + @Column(value = "name") + private String name; +} + diff --git a/cs-database/src/main/java/com/cf/cs/database/pojo/entity/RoleResource.java b/cs-database/src/main/java/com/cf/cs/database/pojo/entity/RoleResource.java new file mode 100644 index 0000000..89566ec --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/pojo/entity/RoleResource.java @@ -0,0 +1,46 @@ +package com.cf.cs.database.pojo.entity; + +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.KeyType; +import com.mybatisflex.annotation.RelationOneToOne; +import com.mybatisflex.annotation.Table; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 权限资源 实体类。 + * + * @author mybatis -flex-helper automatic generation + * @since 1.0 + */ +@Data +@Schema(name = "权限资源") +@Table(value = "rbac_role_resource") +public class RoleResource { + + /** + * 权限id + */ + @Schema(description = "权限id") + @Id(keyType = KeyType.Auto) + private Long roleId; + + /** + * 权限资源id + */ + @Schema(description = "权限资源id") + @Id(keyType = KeyType.Auto) + private Long resourceId; + + /** + * 0: deny, 1: allow + */ + @Schema(description = "0: deny, 1: allow") + @Column(value = "authorize") + private Boolean authorize; + + @RelationOneToOne(selfField = "resourceId", targetField = "id") + @Column(ignore = true) + private ResourceData resources; +} diff --git a/cs-database/src/main/java/com/cf/cs/database/pojo/entity/User.java b/cs-database/src/main/java/com/cf/cs/database/pojo/entity/User.java new file mode 100644 index 0000000..3f9d0bb --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/pojo/entity/User.java @@ -0,0 +1,66 @@ +package com.cf.cs.database.pojo.entity; + +import com.cf.cs.database.config.UuidKeyGenerator; +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.KeyType; +import com.mybatisflex.annotation.RelationOneToOne; +import com.mybatisflex.annotation.Table; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.sql.Timestamp; + +/** + * 用户表(User)表实体类 + * + * @author makejava @163.com + * @since 2023 -12-19 15:14:43 + */ +@Data +@Schema(name = "User", description = "用户表") +@Table("rbac_user") +public class User { + /** + * id + */ + @Schema(description = "id") + @Id(keyType = KeyType.Auto) + private Long id; + + @Schema(description = "uid") + @Id(keyType = KeyType.Generator, value = UuidKeyGenerator.COMMON_UUID) + private String uid; + + /** + * 创建时间 + */ + @Schema(description = "创建时间") + @Column(value = "created_time") + private Timestamp createdTime; + /** + * 创建用户 + */ + @Schema(description = "创建用户") + @Column(value = "gender") + private Long gender; + /** + * 用户名 + */ + @Schema(description = "用户名") + @Column(value = "username") + private String username; + + @Schema(description = "用户权限ID") + @Column(value = "role_id") + private Long roleId; + + @Schema(description = "逻辑删除标记") + @Column(value = "delete_time", isLogicDelete = true) + private Timestamp deleteTime; + + @RelationOneToOne(selfField = "id", targetField = "userId") + @Column(ignore = true) + private UserCredential userCredential; +} + diff --git a/cs-database/src/main/java/com/cf/cs/database/pojo/entity/UserCredential.java b/cs-database/src/main/java/com/cf/cs/database/pojo/entity/UserCredential.java new file mode 100644 index 0000000..cd803f7 --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/pojo/entity/UserCredential.java @@ -0,0 +1,75 @@ +package com.cf.cs.database.pojo.entity; + +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.KeyType; +import com.mybatisflex.annotation.Table; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.sql.Timestamp; + +/** + * 用户认证(UserCredential)表实体类 + * + * @author makejava @163.com + * @since 2023 -12-19 15:14:43 + */ +@Data +@Schema(name = "UserCredential", description = "用户认证") +@Table("rbac_user_credential") +public class UserCredential { + /** + * id + */ + @Schema(description = "id") + @Id(keyType = KeyType.Auto) + private Long id; + /** + * 用户密码 + */ + @Schema(description = "用户密码") + @Column(value = "credential") + private String credential; + /** + * 用户标识 + */ + @Schema(description = "用户标识") + @Column(value = "identifier") + private String identifier; + /** + * 登录类型 + */ + @Schema(description = "登录类型") + @Column(value = "identity_type") + private Integer identityType; + /** + * 用户id + */ + @Schema(description = "用户id") + @Column(value = "user_id") + private Long userId; + /** + * 当前状态(CommonStatus):0-->正常,1-->锁定,2-->禁用,3-->删除 + */ + @Schema(description = "当前状态(CommonStatus):0-->正常,1-->锁定,2-->禁用,3-->删除") + @Column(value = "state") + private Integer state; + /** + * 密码错误次数 + */ + @Schema(description = "密码错误次数") + @Column(value = "error_cnt") + private Integer errorCnt; + /** + * 账户锁定时间 + */ + @Schema(description = "账户锁定时间") + @Column(value = "lock_at") + private Timestamp lockAt; + + @Schema(description = "逻辑删除标记") + @Column(value = "delete_time", isLogicDelete = true) + private Timestamp deleteTime; +} + diff --git a/cs-database/src/main/java/com/cf/cs/database/pojo/po/OperationLogDetails.java b/cs-database/src/main/java/com/cf/cs/database/pojo/po/OperationLogDetails.java new file mode 100644 index 0000000..b2b5c64 --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/pojo/po/OperationLogDetails.java @@ -0,0 +1,31 @@ +package com.cf.cs.database.pojo.po; + +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * The type Operation log details. + * + * @author xajhuang @163.com + */ +@Schema(name = "系统操作日志详细信息") +@Data +@AllArgsConstructor +@NoArgsConstructor +@JsonInclude(JsonInclude.Include.NON_NULL) +public class OperationLogDetails { + @Schema(description = "id") + private Long id; + + @Schema(description = "HTTP 请求头所有参数") + private String requestHeaders; + + @Schema(description = "操作请求参数") + private String request; + + @Schema(description = "操作返回结果") + private String result; +} diff --git a/cs-database/src/main/java/com/cf/cs/database/pojo/po/OperationLogSummary.java b/cs-database/src/main/java/com/cf/cs/database/pojo/po/OperationLogSummary.java new file mode 100644 index 0000000..176abff --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/pojo/po/OperationLogSummary.java @@ -0,0 +1,54 @@ +package com.cf.cs.database.pojo.po; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.sql.Timestamp; + +/** + * The type Operation log summary. + * + * @author xajhuang @163.com + */ +@Schema(name = "系统操作日志摘要数据") +@Data +public class OperationLogSummary { + @Schema(description = "id") + private Long id; + + @Schema(description = "操作模块") + private String module; + + @Schema(description = "操作类型") + private String operationType; + + @Schema(description = "操作状态") + private String operationStatus; + + @Schema(description = "操作说明") + private String description; + + @Schema(description = "请求来源 IP 地址") + private String requestIp; + + @Schema(description = "请求接口") + private String callFunction; + + @Schema(description = "HTTP 请求类型") + private String httpMethod; + + @Schema(description = "请求URI") + private String httpPath; + + @Schema(description = "操作用户id") + private Long userId; + + @Schema(description = "响应时间(ms)") + private Long expendTime; + + @Schema(description = "传输延时(ms)") + private Long transmitDelay; + + @Schema(description = "操作时间") + private Timestamp operationTime; +} diff --git a/cs-database/src/main/java/com/cf/cs/database/pojo/po/PageResults.java b/cs-database/src/main/java/com/cf/cs/database/pojo/po/PageResults.java new file mode 100644 index 0000000..034ac81 --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/pojo/po/PageResults.java @@ -0,0 +1,22 @@ +package com.cf.cs.database.pojo.po; + +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@JsonPropertyOrder({"pageNumber", "pageSize", "totalPage", "totalRow", "items"}) +public class PageResults { + private List items; + private long pageNumber; + private long pageSize; + private long totalPage; + private long totalRow; +} diff --git a/cs-database/src/main/java/com/cf/cs/database/pojo/po/ResPermInfo.java b/cs-database/src/main/java/com/cf/cs/database/pojo/po/ResPermInfo.java new file mode 100644 index 0000000..bfca66c --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/pojo/po/ResPermInfo.java @@ -0,0 +1,34 @@ +package com.cf.cs.database.pojo.po; + +import com.houkunlin.system.dict.starter.json.DictText; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Schema(name = "资源权限信息") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ResPermInfo { + @Schema(description = "资源id") + private Long id; + + @Schema(description = "资源路径") + private String path; + + @Schema(description = "资源名称") + private String name; + + @Schema(description = "资源 HTTP 请求类型") + private String httpMethod; + + @Schema(description = "资源类型 ID") + @DictText(value = "sys_res_type", fieldName = "resTypeName") + private Integer resTypeId; + + @Schema(description = "是否具有访问权限") + private Boolean enable; +} diff --git a/cs-database/src/main/java/com/cf/cs/database/pojo/po/UserInfo.java b/cs-database/src/main/java/com/cf/cs/database/pojo/po/UserInfo.java new file mode 100644 index 0000000..cb122b4 --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/pojo/po/UserInfo.java @@ -0,0 +1,38 @@ +package com.cf.cs.database.pojo.po; + +import com.houkunlin.system.dict.starter.json.DictText; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +import java.sql.Timestamp; + +/** + * The type User info. + * + * @author xajhuang @163.com + */ +@Schema(name = "用户信息") +@Data +@Builder +public class UserInfo { + @Schema(description = "用户uid") + private String uid; + + @Schema(description = "创建时间") + private Timestamp createdTime; + + @Schema(description = "创建用户") + private Long gender; + + @Schema(description = "用户名") + private String username; + + @Schema(description = "用户组ID") + @DictText(value = "sys_role_group", fieldName = "roleIdName") + private Long roleId; + + @Schema(description = "当前状态: 0-->正常,1-->锁定,2-->禁用,3-->删除") + @DictText(value = "CommonStatus", fieldName = "userStatusName") + private Integer userStatus; +} diff --git a/cs-database/src/main/java/com/cf/cs/database/service/OperationLogDataBaseService.java b/cs-database/src/main/java/com/cf/cs/database/service/OperationLogDataBaseService.java new file mode 100644 index 0000000..9ebc6fc --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/service/OperationLogDataBaseService.java @@ -0,0 +1,79 @@ +package com.cf.cs.database.service; + +import com.cf.cs.base.annotation.OperationLogAnnotation; +import com.cf.cs.base.common.ErrorCode; +import com.cf.cs.database.pojo.entity.OperationLog; +import com.cf.cs.database.pojo.po.OperationLogDetails; +import com.cf.cs.database.pojo.po.OperationLogSummary; +import com.mybatisflex.core.paginate.Page; +import com.mybatisflex.core.service.IService; +import jakarta.servlet.http.HttpServletRequest; + +import java.util.List; + +/** + * 系统操作日志 服务层。 + * + * @author mybatis -flex-helper automatic generation + * @since 1.0 + */ +public interface OperationLogDataBaseService extends IService { + /** + * System operation log. + * + * @param call the call + * @param request the request + * @param result the result + * @param annotation the annotation + * @param errorCode the error code + */ + void systemOperationLog(String call, HttpServletRequest request, Object result, OperationLogAnnotation annotation, ErrorCode errorCode); + + /** + * System operation log. + * + * @param call the call + * @param request the request + * @param result the result + * @param module the module + * @param optType the opt type + * @param desc the desc + * @param errorCode the error code + */ + void systemOperationLog(String call, + HttpServletRequest request, + Object result, + String module, + String optType, + String desc, + ErrorCode errorCode); + + /** + * Security operation log. + * + * @param request the request + * @param result the result + * @param errorCode the error code + * @param readme the readme + */ + void securityOperationLog(HttpServletRequest request, Object result, ErrorCode errorCode, String readme); + + /** + * Gets system operation summary. + * + * @param pageNumber the page number + * @param pageSize the page size + * @param totalSize the total size + * @param userName the user name + * @return the system operation summary + */ + Page getSystemOperationSummary(Long pageNumber, Long pageSize, Long totalSize, List userName); + + /** + * Gets system operation details. + * + * @param operationId the operation id + * @return the system operation details + */ + List getSystemOperationDetails(List operationId); +} \ No newline at end of file diff --git a/cs-database/src/main/java/com/cf/cs/database/service/UserDataBaseService.java b/cs-database/src/main/java/com/cf/cs/database/service/UserDataBaseService.java new file mode 100644 index 0000000..6b02d86 --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/service/UserDataBaseService.java @@ -0,0 +1,39 @@ +package com.cf.cs.database.service; + + +import com.cf.cs.database.pojo.entity.User; +import com.cf.cs.database.pojo.po.PageResults; +import com.cf.cs.database.pojo.po.ResPermInfo; +import com.cf.cs.database.pojo.po.UserInfo; +import com.mybatisflex.core.service.IService; + +import java.util.List; + +/** + * 用户表(User)表服务接口 + * + * @author makejava + * @since 2023-12-19 17:35:25 + */ +public interface UserDataBaseService extends IService { + User getAccountUserByName(String username); + + User getAccountUserByUid(String uid); + + User getAccountUserById(Long userId); + + UserInfo getUserInfoById(Long userId); + + UserInfo getUserInfoByUid(String uid); + + UserInfo getUserInfoByUsername(String username); + + UserInfo getCurrentUserInfo(); + + PageResults getAllUserInfo(Long pageNumber, Long pageSize, Long totalSize); + + List getCurrentUserResourcePerm(); + + List getUserResourcePerm(Long userId); +} + diff --git a/cs-database/src/main/java/com/cf/cs/database/service/impl/OperationLogDataBaseServiceImpl.java b/cs-database/src/main/java/com/cf/cs/database/service/impl/OperationLogDataBaseServiceImpl.java new file mode 100644 index 0000000..4dff82b --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/service/impl/OperationLogDataBaseServiceImpl.java @@ -0,0 +1,252 @@ +package com.cf.cs.database.service.impl; + +import com.cf.cs.base.annotation.OperationLogAnnotation; +import com.cf.cs.base.common.ErrorCode; +import com.cf.cs.base.config.CommonConfigure; +import com.cf.cs.base.exception.CommonErrorCodeException; +import com.cf.cs.base.misc.ApiContextUtils; +import com.cf.cs.base.misc.HelperUtils; +import com.cf.cs.base.pojo.po.ApiContext; +import com.cf.cs.database.pojo.entity.OperationLog; +import com.cf.cs.database.mapper.OperationLogMapper; +import com.cf.cs.database.pojo.po.OperationLogDetails; +import com.cf.cs.database.pojo.po.OperationLogSummary; +import com.cf.cs.database.service.OperationLogDataBaseService; +import com.cf.cs.database.service.UserDataBaseService; +import com.jayway.jsonpath.JsonPath; +import com.mybatisflex.core.paginate.Page; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.spring.service.impl.ServiceImpl; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.stereotype.Service; + +import java.sql.Timestamp; +import java.util.List; +import java.util.Optional; + +import static com.cf.cs.database.pojo.entity.table.OperationLogTableDef.OPERATION_LOG; +import static com.cf.cs.database.pojo.entity.table.UserTableDef.USER; +import static com.mybatisflex.core.query.QueryMethods.distinct; +import static com.mybatisflex.core.query.QueryMethods.select; + +/** + * 系统操作日志 服务层实现。 + * + * @author mybatis-flex-helper automatic generation + * @since 1.0 + */ +@Service +@Slf4j +public class OperationLogDataBaseServiceImpl extends ServiceImpl implements OperationLogDataBaseService { + private final int MAX_DB_STRING = 4090; + + @Resource + private ServerProperties serverProperties; + + @Resource + private UserDataBaseService userService; + + @Resource + private OperationLogMapper operationLogMapper; + + @Override + public void systemOperationLog(String call, + HttpServletRequest request, + Object result, + OperationLogAnnotation annotation, + ErrorCode errorCode) { + if (annotation != null) { + systemOperationLog(call, request, result, annotation.OperationModule(), annotation.OperationType(), + annotation.OperationDesc(), errorCode); + } else { + systemOperationLog(call, request, result, "", "", "", errorCode); + } + } + + @Override + public void securityOperationLog(HttpServletRequest request, Object result, ErrorCode errorCode, String readme) { + try { + ApiContext ctx = ApiContextUtils.get(); + OperationLog optLog = new OperationLog(); + + if (request.getRequestURI().startsWith(CommonConfigure.PROJECT_PREFIX_URL + "/error")) { + return; + } + + optLog.setOperationStatus(errorCode.getDescription()); + + //获取注解操作信息 + optLog.setModule("系统安全模块"); + optLog.setOperationType("认证/鉴权"); + optLog.setDescription(readme); + optLog.setUserId(-1L); + + //操作时间 + optLog.setOperationTime(new Timestamp(System.currentTimeMillis())); + // 请求方法 + optLog.setHttpMethod(request.getMethod()); + // 请求URL + String prefixUrl = Optional.ofNullable(serverProperties.getServlet().getContextPath()).orElse(""); + String url = request.getRequestURI().replaceFirst("^" + prefixUrl, ""); + optLog.setHttpPath(url); + + // 仅处理 RESTful 接口 + if (url.startsWith("/api")) { + // 登录接口不包含 Authorization 信息 + if (url.lastIndexOf("login") != -1) { + optLog.setCallFunction("login"); + optLog.setUserId(ctx.getId() != null ? ctx.getId() : -1L); + } else { + if (url.lastIndexOf("logout") != -1) { + optLog.setCallFunction("logout"); + } + + if (HelperUtils.stringNotEmptyOrNull(ctx.getJwt())) { + optLog.setDescription(ctx.getUsername() + " " + optLog.getDescription()); + optLog.setUserId(ctx.getId() != null ? ctx.getId() : -1L); + } + } + } + + //操作IP + optLog.setRequestIp(HelperUtils.getHttpRequestSrcIp(request)); + //返回值信息 + optLog.setResult(HelperUtils.truncateString(HelperUtils.getJson(result), MAX_DB_STRING)); + // 请求Headers + optLog.setRequestHeaders(HelperUtils.truncateString(HelperUtils.getHttpRequestHeaders(request), MAX_DB_STRING)); + // 响应延时 + optLog.setExpendTime(System.currentTimeMillis() - ctx.getRequestTime()); + // 请求信息 + String reqJson = ctx.getRequestBody(); + optLog.setRequest(HelperUtils.truncateString(reqJson, MAX_DB_STRING)); + + if (HelperUtils.stringNotEmptyOrNull(reqJson)) { + // 传输延时 + Long reqTime = Optional.ofNullable((Long) JsonPath.read(reqJson, "$.timeStamp")).orElse(0L); + optLog.setTransmitDelay(ctx.getRequestTime() - reqTime); + } + + //保存日志 + operationLogMapper.insert(optLog, true); + log.trace("{}", HelperUtils.getJson(optLog)); + } catch (Exception e) { + log.error(e.getMessage()); + } + } + + @Override + public Page getSystemOperationSummary(Long pageNumber, + Long pageSize, + Long totalSize, + List userName) { + QueryWrapper wrapper; + + ApiContext ctx = ApiContextUtils.get(); + + String username = ctx.getUsername(); + // 当前已经有合法的认证用户 + if (HelperUtils.stringNotEmptyOrNull(username)) { + if (userName != null && !userName.isEmpty()) { + List idArray = userName.stream() + .filter(k -> userService.getAccountUserByName(k) != null) + .map(k -> userService.getAccountUserByName(k).getId()) + .toList(); + + wrapper = new QueryWrapper().select(OPERATION_LOG.ALL_COLUMNS) + .from(OPERATION_LOG.as("o"), USER.as("u1")) + .where(OPERATION_LOG.USER_ID.eq(USER.ID) + .and(USER.ID.in(idArray)) + .and(USER.ROLE_ID.ge( + select(distinct(USER.ROLE_ID)).from( + USER.as("u")) + .where(USER.ID.eq( + ctx.getId()))))); + } else { + wrapper = new QueryWrapper().select(OPERATION_LOG.ALL_COLUMNS) + .from(OPERATION_LOG.as("o"), USER.as("u1")) + .where(OPERATION_LOG.USER_ID.eq(USER.ID) + .and(USER.ROLE_ID.ge( + select(distinct(USER.ROLE_ID)).from( + USER.as("u")) + .where(USER.ID.eq( + ctx.getId()))))); + } + + return operationLogMapper.paginateAs(pageNumber, pageSize, totalSize, wrapper, OperationLogSummary.class); + } else { + log.error("Current User is not authentication."); + throw new CommonErrorCodeException(ErrorCode.ERR_LOGOUT); + } + } + + @Override + public List getSystemOperationDetails(List operationId) { + QueryWrapper wrapper = QueryWrapper.create() + .from(OPERATION_LOG) + .select() + .where(OPERATION_LOG.ID.in(operationId)); + return operationLogMapper.selectListByQueryAs(wrapper, OperationLogDetails.class); + } + + @Override + public void systemOperationLog(String call, + HttpServletRequest request, + Object result, + String module, + String optType, + String desc, + ErrorCode errorCode) { + try { + ApiContext ctx = ApiContextUtils.get(); + OperationLog optLog = new OperationLog(); + + if (request.getRequestURI().startsWith(CommonConfigure.PROJECT_PREFIX_URL + "/error")) { + return; + } + + optLog.setOperationStatus(errorCode.getDescription()); + optLog.setCallFunction(call); + //获取注解操作信息 + optLog.setModule(module); + optLog.setOperationType(optType); + optLog.setDescription(desc); + //操作时间 + optLog.setOperationTime(new Timestamp(System.currentTimeMillis())); + // 请求方法 + optLog.setHttpMethod(request.getMethod()); + // 请求URL + String prefixUrl = Optional.ofNullable(serverProperties.getServlet().getContextPath()).orElse(""); + String url = request.getRequestURI().replaceFirst("^" + prefixUrl, ""); + optLog.setHttpPath(url); + + //操作用户 + optLog.setUserId(ctx.getId()); + + //操作IP + optLog.setRequestIp(HelperUtils.getHttpRequestSrcIp(request)); + //返回值信息 + optLog.setResult(HelperUtils.truncateString(HelperUtils.getJson(result), MAX_DB_STRING)); + // 请求Headers + optLog.setRequestHeaders(HelperUtils.truncateString(HelperUtils.getHttpRequestHeaders(request), MAX_DB_STRING)); + // 请求信息 + String reqJson = ctx.getRequestBody(); + optLog.setRequest(HelperUtils.truncateString(reqJson, MAX_DB_STRING)); + + // 响应延时 + optLog.setExpendTime(System.currentTimeMillis() - ctx.getRequestTime()); + if (HelperUtils.stringNotEmptyOrNull(reqJson)) { + // 传输延时 + Long reqTime = Optional.ofNullable((Long) JsonPath.read(reqJson, "$.timeStamp")).orElse(0L); + optLog.setTransmitDelay(ctx.getRequestTime() - reqTime); + } + + //保存日志 + operationLogMapper.insert(optLog, true); + log.trace("{}", HelperUtils.getJson(optLog)); + } catch (Exception ignored) { + } + } +} \ No newline at end of file diff --git a/cs-database/src/main/java/com/cf/cs/database/service/impl/UserDataBaseServiceImpl.java b/cs-database/src/main/java/com/cf/cs/database/service/impl/UserDataBaseServiceImpl.java new file mode 100644 index 0000000..c3914aa --- /dev/null +++ b/cs-database/src/main/java/com/cf/cs/database/service/impl/UserDataBaseServiceImpl.java @@ -0,0 +1,306 @@ +package com.cf.cs.database.service.impl; + + +import com.cf.cs.base.common.ErrorCode; +import com.cf.cs.base.exception.CommonErrorCodeException; +import com.cf.cs.base.misc.ApiContextUtils; +import com.cf.cs.base.misc.HelperUtils; +import com.cf.cs.database.mapper.ResourceDataMapper; +import com.cf.cs.database.mapper.ResourceTypeMapper; +import com.cf.cs.database.mapper.RoleMapper; +import com.cf.cs.database.mapper.RoleResourceMapper; +import com.cf.cs.database.mapper.UserCredentialMapper; +import com.cf.cs.database.mapper.UserMapper; +import com.cf.cs.database.pojo.entity.ResourceData; +import com.cf.cs.database.pojo.entity.RoleResource; +import com.cf.cs.database.pojo.entity.User; +import com.cf.cs.database.pojo.po.PageResults; +import com.cf.cs.database.pojo.po.ResPermInfo; +import com.cf.cs.database.pojo.po.UserInfo; +import com.cf.cs.database.service.UserDataBaseService; +import com.mybatisflex.core.paginate.Page; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.spring.service.impl.ServiceImpl; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static com.cf.cs.database.pojo.entity.table.RoleResourceTableDef.ROLE_RESOURCE; +import static com.cf.cs.database.pojo.entity.table.UserTableDef.USER; + +/** + * 用户表(User)表服务实现类 + * + * @author makejava + * @since 2023-12-19 17:35:26 + */ +@Service("userService") +@Slf4j +public class UserDataBaseServiceImpl extends ServiceImpl implements UserDataBaseService { + private final Map resourceType = new HashMap<>(); + + @Resource + private ResourceDataMapper resDataMapper; + + @Resource + private RoleResourceMapper roleResourceMapper; + + @Resource + private RoleMapper roleMapper; + + @Resource + private UserMapper userMapper; + + @Resource + private UserCredentialMapper userCredentialMapper; + + @Resource + private ResourceTypeMapper resourceTypeMapper; + + private User queryUser(QueryWrapper wrapper) { + return this.getMapper().selectOneWithRelationsByQuery(wrapper); + } + + @Override + public User getAccountUserByName(String username) { + QueryWrapper wrapper = QueryWrapper.create().from(USER).select().where(USER.USERNAME.eq(username)); + return (username == null || username.isEmpty()) ? null : queryUser(wrapper); + } + + @Override + public User getAccountUserByUid(String uid) { + QueryWrapper wrapper = QueryWrapper.create().from(USER).select().where(USER.UID.eq(uid)); + return (!HelperUtils.stringNotEmptyOrNull(uid)) ? null : queryUser(wrapper); + } + + @Override + public User getAccountUserById(Long userId) { + QueryWrapper wrapper = QueryWrapper.create().from(USER).select().where(USER.ID.eq(userId)); + return (userId == null) ? null : queryUser(wrapper); + } + + @Override + public UserInfo getUserInfoById(Long userId) { + // 获取用户信息 + QueryWrapper wrapper = QueryWrapper.create().from(USER).select().where(USER.ID.eq(userId)); + User user = queryUser(wrapper); + + if (user == null) { + log.error("Current User is not exists."); + throw new CommonErrorCodeException(ErrorCode.ERR_USERNOTFOUND); + } + + // 低优先级用户不能获取高优先级用户信息 + if (verifyCurrentExceedPermission(user)) { + throw new CommonErrorCodeException(ErrorCode.ERR_PERMISSION); + } + + return UserInfo.builder().uid(user.getUid()).createdTime(user.getCreatedTime()).gender(user.getGender()).username( + user.getUsername()).roleId(user.getRoleId()).userStatus(user.getUserCredential().getState()).build(); + } + + @Override + public UserInfo getUserInfoByUid(String uid) { + // 获取用户信息 + QueryWrapper wrapper = QueryWrapper.create().from(USER).select().where(USER.UID.eq(uid)); + User user = queryUser(wrapper); + + if (user == null) { + log.error("Current User is not exists."); + throw new CommonErrorCodeException(ErrorCode.ERR_USERNOTFOUND); + } + + // 低优先级用户不能获取高优先级用户信息 + if (verifyCurrentExceedPermission(user)) { + throw new CommonErrorCodeException(ErrorCode.ERR_PERMISSION); + } + + return UserInfo.builder().uid(user.getUid()).createdTime(user.getCreatedTime()).gender(user.getGender()).username( + user.getUsername()).roleId(user.getRoleId()).userStatus(user.getUserCredential().getState()).build(); + } + + @Override + public UserInfo getUserInfoByUsername(String username) { + // 获取用户信息 + QueryWrapper wrapper = QueryWrapper.create().from(USER).select().where(USER.USERNAME.eq(username)); + User user = queryUser(wrapper); + + if (user == null) { + log.error("Current User({}) is not exists.", username); + throw new CommonErrorCodeException(ErrorCode.ERR_USERNOTFOUND); + } + + return getUserInfoById(user.getId()); + } + + @Override + public UserInfo getCurrentUserInfo() { + String username = ApiContextUtils.get().getUsername(); + User user = getAccountUserByName(username); + + if (user == null) { + log.error("Current login user not found: [{}]", username); + throw new CommonErrorCodeException(ErrorCode.ERR_TOKENNOTFOUND); + } + + return UserInfo.builder().uid(user.getUid()).createdTime(user.getCreatedTime()).gender(user.getGender()).username( + user.getUsername()).roleId(user.getRoleId()).userStatus(user.getUserCredential().getState()).build(); + } + + @Override + public PageResults getAllUserInfo(Long pageNumber, Long pageSize, Long totalSize) { + QueryWrapper wrapper = QueryWrapper.create().from(USER).select(); + List ui = new ArrayList<>(); + + Page user = userMapper.paginateWithRelations(pageNumber, pageSize, totalSize, wrapper); + + user.getRecords().forEach(k -> ui.add(UserInfo.builder() + .uid(k.getUid()) + .createdTime(k.getCreatedTime()) + .gender(k.getGender()) + .username(k.getUsername()) + .roleId(k.getRoleId()) + .userStatus(k.getUserCredential().getState()) + .build())); + + return PageResults.builder() + .items(ui) + .pageNumber(user.getPageNumber()) + .pageSize(user.getPageSize()) + .totalPage(user.getTotalPage()) + .totalRow(user.getTotalRow()) + .build(); + } + + @Override + public List getCurrentUserResourcePerm() { + List res; + + String username = ApiContextUtils.get().getUsername(); + User user = getAccountUserByName(username); + + if (user == null) { + log.error("Current login user not found: [{}]", username); + throw new CommonErrorCodeException(ErrorCode.ERR_TOKENNOTFOUND); + } + + List result = new ArrayList<>(); + QueryWrapper wrapper = QueryWrapper.create().from(ROLE_RESOURCE).select().where( + ROLE_RESOURCE.ROLE_ID.eq(user.getId())); + List roleRes = roleResourceMapper.selectListWithRelationsByQuery(wrapper); + + roleRes.forEach(k -> result.add(ResPermInfo.builder() + .id(k.getResourceId()) + .name(k.getResources().getName()) + .path(k.getResources().getPath()) + //.resType(k.getResources().getResType().getTypeId()) + .resTypeId(k.getResources().getResType().getTypeId()) + .httpMethod(k.getResources().getHttpMethod()) + .enable(k.getAuthorize()) + .build())); + + res = resDataMapper.selectAllWithRelations().stream().filter( + k -> roleRes.stream().noneMatch(m -> m.getResources().getPath().equals(k.getPath()))).toList(); + + res.forEach(k -> result.add(ResPermInfo.builder() + .id(k.getId()) + .name(k.getName()) + .path(k.getPath()) + .httpMethod(k.getHttpMethod()) + .resTypeId(k.getResType().getTypeId()) + .enable(false) + .build())); + + return result; + } + + @Override + public List getUserResourcePerm(Long userId) { + List res; + + // 获取用户信息 + QueryWrapper wrapper = QueryWrapper.create().from(USER).select().where(USER.ID.eq(userId)); + User user = queryUser(wrapper); + + if (user == null) { + log.error("Current User is not exists."); + throw new CommonErrorCodeException(ErrorCode.ERR_USERNOTFOUND); + } + + // 低优先级用户不能获取高优先级用户信息 + if (verifyCurrentExceedPermission(user)) { + throw new CommonErrorCodeException(ErrorCode.ERR_PERMISSION); + } + + List result = new ArrayList<>(); + wrapper = QueryWrapper.create().from(ROLE_RESOURCE).select().where(ROLE_RESOURCE.ROLE_ID.eq(user.getId())); + List roleRes = roleResourceMapper.selectListWithRelationsByQuery(wrapper); + + roleRes.forEach(k -> result.add(ResPermInfo.builder() + .id(k.getResourceId()) + .name(k.getResources().getName()) + .path(k.getResources().getPath()) + .httpMethod(k.getResources().getHttpMethod()) + //.resType(k.getResources().getResType().getTypeId()) + .resTypeId(k.getResources().getResType().getTypeId()) + .enable(k.getAuthorize()) + .build())); + + res = resDataMapper.selectAllWithRelations().stream().filter( + k -> roleRes.stream().noneMatch(m -> m.getResources().getPath().equals(k.getPath()))).toList(); + + res.forEach(k -> result.add(ResPermInfo.builder() + .id(k.getId()) + .name(k.getName()) + .path(k.getPath()) + .resTypeId(k.getResType().getTypeId()) + .httpMethod(k.getHttpMethod()) + .enable(false) + .build())); + + return result; + } + + private boolean verifyCurrentExceedPermission(User accessUser) { + String loginUsername = ApiContextUtils.get().getUsername(); + + if (!HelperUtils.stringNotEmptyOrNull(loginUsername)) { + log.error("Current login user not found: [{}]", accessUser.getUsername()); + throw new CommonErrorCodeException(ErrorCode.ERR_TOKENNOTFOUND); + } + + User logUser = getAccountUserByName(loginUsername); + + if (logUser == null) { + log.error("Current login user not found: [{}]", loginUsername); + throw new CommonErrorCodeException(ErrorCode.ERR_TOKENNOTFOUND); + } + + // 低优先级用户不能获取高优先级用户信息 + if (logUser.getId() <= accessUser.getRoleId()) { + return false; + } + + log.error("Permission check deny: login user{}, request user{}", logUser.getId(), accessUser.getRoleId()); + return true; + } + + @PostConstruct + public void init() { + // 在组件初始化后执行的逻辑 + resourceTypeMapper.selectAll().forEach(k -> { + if (!resourceType.containsKey(k.getTypeId())) { + resourceType.put(k.getTypeId(), k.getName()); + } + }); + // 可以在这里进行一些初始化操作,如初始化参数、加载数据等 + } +} diff --git a/cs-database/src/main/resources/rbac/clean_database.sql b/cs-database/src/main/resources/rbac/clean_database.sql new file mode 100644 index 0000000..ed4cc61 --- /dev/null +++ b/cs-database/src/main/resources/rbac/clean_database.sql @@ -0,0 +1,15 @@ +SET NAMES utf8mb3; +SET FOREIGN_KEY_CHECKS = 0; + +DROP TABLE IF EXISTS `rbac_role_resource`; +DROP TABLE IF EXISTS `rbac_role`; +DROP TABLE IF EXISTS `rbac_user`; +DROP TABLE IF EXISTS `rbac_user_credential`; +DROP TABLE IF EXISTS `rbac_resource_data`; +DROP TABLE IF EXISTS `rbac_resource_type`; + + +DROP TABLE IF EXISTS `sys_operation_log`; +DROP TABLE IF EXISTS `sys_dict_data`; +DROP TABLE IF EXISTS `sys_dict_type`; +SET FOREIGN_KEY_CHECKS = 1; \ No newline at end of file diff --git a/cs-database/src/main/resources/rbac/data.sql b/cs-database/src/main/resources/rbac/data.sql new file mode 100644 index 0000000..b4298bf --- /dev/null +++ b/cs-database/src/main/resources/rbac/data.sql @@ -0,0 +1,212 @@ +-- 关闭外键约束检查 +set foreign_key_checks = 0; + +INSERT IGNORE INTO rbac_user (id, uid, username, gender, role_id) VALUES (1, 'e472582b-88b9-4fe8-8ca7-c8e3b0aa2851', 'admin', 0, 1); +INSERT IGNORE INTO rbac_user (id, uid, username, gender, role_id) VALUES (2, '22adc004-a9f6-4a5d-8be3-ae3629a4ba1b', 'user', 1, 3); +INSERT IGNORE INTO rbac_user (id, uid, username, gender, role_id) VALUES (3, '44ede496-d538-4a1d-afb9-bc409f752738', 'guest', 0, 4); + +INSERT IGNORE INTO rbac_role (id, available, description, name) VALUES (1, true, '超级管理员可以对企业内的所有用户进行管理,请谨慎修改超管权限', 'ADMIN'); +INSERT IGNORE INTO rbac_role (id, available, description, name) VALUES (2, true, '项目开发人员', 'DEVELOPMENT'); +INSERT IGNORE INTO rbac_role (id, available, description, name) VALUES (3, true, '普通的用户', 'USER'); +INSERT IGNORE INTO rbac_role (id, available, description, name) VALUES (4, false, '系统访客,不需要认证,最小权限', 'GUEST'); + +INSERT IGNORE INTO rbac_user_credential (id, credential, identifier, identity_type, user_id, state, error_cnt) VALUES (1, '$2a$10$5Arh4lqTumXH5b5J0cQ/D.Sc3Fs0wlB1otRm91PTep3q/dxjy0VyC', 'admin', 0, 1, 0, 0); +INSERT IGNORE INTO rbac_user_credential (id, credential, identifier, identity_type, user_id, state, error_cnt) VALUES (2, '$2a$10$wCwH9D1.ushoN7ywoh0arepzP79vZuyy6LuKBtEVY3quQiQMjQe.q', 'user', 0, 2, 0, 0); +INSERT IGNORE INTO rbac_user_credential (id, credential, identifier, identity_type, user_id, state, error_cnt) VALUES (3, '$2a$10$IUZ.LdcBLWwmNhNPhy/zSOiDPweRp0kkiVn7I5gULTj9CgRUfhu.q', 'guest', 0, 3, 0, 0); + +-- ---------------------------- +-- Records of resource_type +-- ---------------------------- +INSERT IGNORE INTO rbac_resource_type VALUES(0, '路由'); +INSERT IGNORE INTO rbac_resource_type VALUES(1, '菜单'); +INSERT IGNORE INTO rbac_resource_type VALUES(2, '按钮'); + +-- ---------------------------- +-- Records of resource +-- ---------------------------- +INSERT IGNORE INTO rbac_resource_data VALUES (1, '98ca121c-56e7-4aa7-9351-8d9633f768a1', '/api/version', '获取版本信息', 'GET', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (2, '673f62f0-3ca7-41f1-82d0-8e3d2ac47512', '/api/version', '获取版本信息', 'POST', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (100, 'f3b718ee-aa58-4b14-b466-1412b6e35c74', '/api/operation/summary', '获取操作日志摘要', 'POST', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (101, 'acba3926-6e5d-4a80-a957-a045b4e76c7e', '/api/operation/details', '获取操作日志详情', 'POST', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (200, 'c50d5501-4483-4556-bdb5-1c1cd66c6980', '/api/permission/allRoles', '获取当前所有用户组', 'GET', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (201, '21374966-ab7f-4d22-82af-6199a6c14616', '/api/permission/resourcePermission', '获取当前用户资源权限', 'GET', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (202, '86114665-35d8-40b9-86d0-84fdbda4eadc', '/api/permission/resourcePermission', '获取用户资源权限', 'POST', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (203, '9434daf9-ebb9-48ab-8c4e-ecf8edef9f76', '/api/permission/resource', '注册新资源', 'PUT', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (204, '995e26c0-82df-4751-8b2d-a62b29cd7385', '/api/permission/resource', '注册新资源', 'DELETE', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (300, '58e36be5-f725-4d98-bd7d-8f7377219ed6', '/api/user/userInfo', '获取用户信息', 'GET', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (301, 'fa2b3740-8672-49d3-9792-25976b767ade', '/api/user/userInfo', '获取用户信息', 'POST', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (302, '221c8d8e-c47a-4200-88a8-34d374a76d01', '/api/user/register', '注册新用户', 'PUT', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (303, '8adf6875-2be4-459e-9c1d-3bb87114cb08', '/api/user/remove', '删除用户', 'DELETE', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (304, '4c6c859b-2625-45eb-83b8-1426ff96dbe6', '/api/user/userList', '分页获取当前所有用户', 'POST', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (400, '8ac928d8-5a6a-47c7-8697-0fb9ebd7249d', '/api/dict/enum/allDict', '获取所以枚举字典列表', 'GET', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (401, '9ecf1662-f891-4829-8d3e-81c42bf22e2a', '/api/dict/enum/dictContent', '获取枚举字典详细内容', 'POST', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (402, 'C083F441-9624-AF2C-B353-0768F9C0A932', '/api/dict/user/add', '新增用户字典', 'PUT', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (403, '953cea37-cc7a-4e7e-bd86-cb3c14daa8c4', '/api/dict/user/upgrade', '修改用户字典', 'POST', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (404, '247674fb-759d-4b01-8d35-2c0436d2ed99', '/api/dict/user/delete', '删除用户字典', 'DELETE', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (405, '54b43614-45c6-4672-a1d8-fa8f326d5e53', '/api/dict/user/allDict', '分页获取所有用户字典', 'POST', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (406, 'e441dbb4-b844-461c-a5f8-07ee3fa658cc', '/api/dict/user/getDictContent', '获取用户字典详细信息', 'POST', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (407, 'c803571e-ba0d-4f3d-bcc8-76488b1af22a', '/api/dict/user/addDictContent', '新增用户字典详细信息', 'PUT', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (408, '99106f7a-6c4e-4438-ad40-65ed9417d0b4', '/api/dict/user/upgradeDictContent', '更新用户字典详细信息', 'POST', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (409, 'a4c04e8f-d495-46ca-b67e-79cc9a91d623', '/api/dict/user/deleteDictContent', '删除用户字典详细信息', 'DELETE', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (500, '3e7b6439-8d66-4409-84db-16fcbb115215', '/api/systemInfo/osInfo', '获取操作系统信息', 'GET', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (501, 'a958211f-083e-4a2d-b21d-5442090486d2', '/api/systemInfo/processorInfo', '获取系统处理器信息', 'GET', 0); +INSERT IGNORE INTO rbac_resource_data VALUES (502, 'f5dcb609-692d-4f81-b3fa-0f4dc3c891fb', '/api/systemInfo/hwInfo', '获取系统硬件信息', 'GET', 0); + +-- ---------------------------- +-- Records of role_resource +-- (role_id, resource_id, authorize) +-- ---------------------------- +INSERT IGNORE INTO rbac_role_resource VALUES (1, 1, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 2, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 100, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 101, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 200, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 201, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 202, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 203, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 204, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 300, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 301, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 302, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 303, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 304, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 400, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 401, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 402, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 403, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 404, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 405, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 406, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 407, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 408, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 409, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 500, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 501, 1); +INSERT IGNORE INTO rbac_role_resource VALUES (1, 502, 1); +# INSERT IGNORE INTO role_resource (role_id, resource_id, authorize) VALUES (2, 1, 1); +# INSERT IGNORE INTO role_resource (role_id, resource_id, authorize) VALUES (2, 2, 1); +# INSERT IGNORE INTO role_resource (role_id, resource_id, authorize) VALUES (2, 3, 1); +# INSERT IGNORE INTO role_resource (role_id, resource_id, authorize) VALUES (2, 4, 1); +# INSERT IGNORE INTO role_resource (role_id, resource_id, authorize) VALUES (2, 5, 1); +# +# INSERT IGNORE INTO role_resource (role_id, resource_id, authorize) VALUES (3, 1, 1); +# INSERT IGNORE INTO role_resource (role_id, resource_id, authorize) VALUES (3, 3, 1); +# INSERT IGNORE INTO role_resource (role_id, resource_id, authorize) VALUES (3, 4, 1); +# INSERT IGNORE INTO role_resource (role_id, resource_id, authorize) VALUES (3, 5, 1); +# +# INSERT IGNORE INTO role_resource (role_id, resource_id, authorize) VALUES (4, 1, 1); +# INSERT IGNORE INTO role_resource (role_id, resource_id, authorize) VALUES (4, 3, 1); +# INSERT IGNORE INTO role_resource (role_id, resource_id, authorize) VALUES (4, 4, 1); +# INSERT IGNORE INTO role_resource (role_id, resource_id, authorize) VALUES (4, 5, 1); + +-- ---------------------------- +-- Records of casbin_rule +-- ---------------------------- +# INSERT IGNORE INTO `casbin_rule` VALUES (1, 'g', 'admin', 'ADMIN', NULL, NULL, NULL, NULL); +# INSERT IGNORE INTO `casbin_rule` VALUES (2, 'g', 'user', 'DEVELOPMENT', NULL, NULL, NULL, NULL); +# INSERT IGNORE INTO `casbin_rule` VALUES (3, 'g', 'development', 'USER', NULL, NULL, NULL, NULL); +# INSERT IGNORE INTO `casbin_rule` VALUES (4, 'g', 'guest', 'GUEST', NULL, NULL, NULL, NULL); +# +# INSERT IGNORE INTO `casbin_rule` VALUES (5, 'p', 'ADMIN', '/api/version', '(GET)|(POST)', 'allow', NULL, NULL); +# INSERT IGNORE INTO `casbin_rule` VALUES (6, 'p', 'DEVELOPMENT', '/api/version', 'GET', 'allow', NULL, NULL); +# INSERT IGNORE INTO `casbin_rule` VALUES (7, 'p', 'USER', '/api/version', 'GET', 'allow', NULL, NULL); +# INSERT IGNORE INTO `casbin_rule` VALUES (8, 'p', 'GUEST', '/api/version', 'GET', 'allow', NULL, NULL); +# +# INSERT IGNORE INTO `casbin_rule` VALUES (9, 'p', 'DEVELOPMENT', '/swagger-ui/*', 'GET', 'allow', NULL, NULL); +# INSERT IGNORE INTO `casbin_rule` VALUES (10, 'p', 'USER', '/swagger-ui/*', 'GET', 'deny', NULL, NULL); +# INSERT IGNORE INTO `casbin_rule` VALUES (11, 'p', 'GUEST', '/swagger-ui/*', 'GET', 'deny', NULL, NULL); + +# INSERT IGNORE INTO user_role (user_id, role_id) VALUES (1, 1); +# INSERT IGNORE INTO user_role (user_id, role_id) VALUES (2, 3); +# INSERT IGNORE INTO user_role (user_id, role_id) VALUES (3, 4); +# +# INSERT IGNORE INTO resource (id, name, parent_ids, permission, type, url, parent_id) VALUES (1, '根节点', null, '*', null, null, null); +# INSERT IGNORE INTO resource (id, name, parent_ids, permission, type, url, parent_id) VALUES (2, '仪表盘', null, 'dashboard', 0, '/dashboard', 1); +# INSERT IGNORE INTO resource (id, name, parent_ids, permission, type, url, parent_id) VALUES (3, '系统管理', null, 'sys', 0, '/sys', 1); +# INSERT IGNORE INTO resource (id, name, parent_ids, permission, type, url, parent_id) VALUES (4, '用户管理', null, 'user:view', 0, '/users', 3); +# INSERT IGNORE INTO resource (id, name, parent_ids, permission, type, url, parent_id) VALUES (5, '角色管理', null, 'role:view', 0, '/roles', 3); +# INSERT IGNORE INTO resource (id, name, parent_ids, permission, type, url, parent_id) VALUES (6, '权限资源', null, 'resource:view', 0, '/resources', 3); +# INSERT IGNORE INTO resource (id, name, parent_ids, permission, type, url, parent_id) VALUES (7, '查看用户', null, 'user:view', 1, null, 4); +# INSERT IGNORE INTO resource (id, name, parent_ids, permission, type, url, parent_id) VALUES (8, '新增用户', null, 'user:create', 1, null, 4); +# INSERT IGNORE INTO resource (id, name, parent_ids, permission, type, url, parent_id) VALUES (9, '修改用户', null, 'user:update', 1, null, 4); +# INSERT IGNORE INTO resource (id, name, parent_ids, permission, type, url, parent_id) VALUES (10, '删除用户', null, 'user:delete', 1, null, 4); +# INSERT IGNORE INTO resource (id, name, parent_ids, permission, type, url, parent_id) VALUES (11, '查看角色', null, 'role:view', 1, null, 5); +# INSERT IGNORE INTO resource (id, name, parent_ids, permission, type, url, parent_id) VALUES (12, '新增角色', null, 'role:create', 1, null, 5); +# INSERT IGNORE INTO resource (id, name, parent_ids, permission, type, url, parent_id) VALUES (13, '修改角色', null, 'role:update', 1, null, 5); +# INSERT IGNORE INTO resource (id, name, parent_ids, permission, type, url, parent_id) VALUES (14, '删除角色', null, 'role:delete', 1, null, 5); +# INSERT IGNORE INTO resource (id, name, parent_ids, permission, type, url, parent_id) VALUES (15, '查看资源', null, 'resource:view', 1, null, 6); +# INSERT IGNORE INTO resource (id, name, parent_ids, permission, type, url, parent_id) VALUES (16, '新增资源', null, 'resource:create', 1, null, 6); +# INSERT IGNORE INTO resource (id, name, parent_ids, permission, type, url, parent_id) VALUES (17, '修改资源', null, 'resource:update', 1, null, 6); +# INSERT IGNORE INTO resource (id, name, parent_ids, permission, type, url, parent_id) VALUES (18, '删除资源', null, 'resource:delete', 1, null, 6); +# INSERT IGNORE INTO resource (id, name, parent_ids, permission, type, url, parent_id) VALUES (19, '新增组织架构', null, 'organization:create', 1, null, 4); +# INSERT IGNORE INTO resource (id, name, parent_ids, permission, type, url, parent_id) VALUES (20, '修改组织架构', null, 'organization:update', 1, null, 4); +# INSERT IGNORE INTO resource (id, name, parent_ids, permission, type, url, parent_id) VALUES (21, '删除组织架构', null, 'organization:delete', 1, null, 4); +# INSERT IGNORE INTO resource (id, name, parent_ids, permission, type, url, parent_id) VALUES (22, '操作日志', null, 'log:view', 0, '/logs', 3); +# INSERT IGNORE INTO resource (id, name, parent_ids, permission, type, url, parent_id) VALUES (23, '清空日志', null, 'log:clean', 1, null, 22); +# INSERT IGNORE INTO resource (id, name, parent_ids, permission, type, url, parent_id) VALUES (24, '查看日志', null, 'log:view', 1, null, 22); +# +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (1, 2); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (1, 3); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (1, 4); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (1, 5); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (1, 6); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (1, 7); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (1, 8); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (1, 9); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (1, 10); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (1, 11); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (1, 12); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (1, 13); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (1, 14); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (1, 15); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (1, 16); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (1, 17); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (1, 18); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (1, 19); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (1, 20); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (1, 21); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (1, 22); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (1, 23); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (1, 24); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (2, 2); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (2, 3); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (2, 6); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (2, 15); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (2, 16); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (2, 17); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (2, 18); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (2, 22); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (2, 23); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (2, 24); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (3, 2); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (4, 2); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (4, 3); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (4, 4); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (4, 5); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (4, 6); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (4, 7); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (4, 11); +# INSERT IGNORE INTO role_resource (role_id, resource_id) VALUES (4, 15); + +#insert into sys_dict_type values(1, '用户性别', 'sys_user_sex', '0', 'admin', sysdate(), '', null, '用户性别列表'); +#INSERT IGNORE INTO rbac_user (id, uid, username, gender, role_id) VALUES (3, '44ede496-d538-4a1d-afb9-bc409f752738', 'guest', 0, 4); +INSERT IGNORE INTO sys_dict_type (id, dict_name, dict_type, create_by, remark) VALUES (1, '资源类型', 'sys_res_type', 'admin', '资源类型列表'); +INSERT IGNORE INTO sys_dict_type (id, dict_name, dict_type, create_by, remark) VALUES (2, '用户组', 'sys_role_group', 'admin', '用户组列表'); + + +INSERT IGNORE INTO sys_dict_data VALUES (1, 1, '路由', 0, 1, '', '','Y', 'admin', CURRENT_TIMESTAMP(6), '', null, 'URI 路由资源', null); +INSERT IGNORE INTO sys_dict_data VALUES (2, 2, '菜单', 1, 1, '', '','N', 'admin', CURRENT_TIMESTAMP(6), '', null, 'UI 菜单资源', null); +INSERT IGNORE INTO sys_dict_data VALUES (3, 3, '按钮', 2, 1, '', '','N', 'admin', CURRENT_TIMESTAMP(6), '', null, 'UI 按钮资源', null); + +INSERT IGNORE INTO sys_dict_data VALUES (4, 1, 'ADMIN', 1, 2, '', '','N', 'admin', CURRENT_TIMESTAMP(6), '', null, '超级管理员可以对企业内的所有用户进行管理,请谨慎修改超管权限', null); +INSERT IGNORE INTO sys_dict_data VALUES (5, 2, 'DEVELOPMENT', 2, 2, '', '','N', 'admin', CURRENT_TIMESTAMP(6), '', null, '项目开发人员', null); +INSERT IGNORE INTO sys_dict_data VALUES (6, 3, 'USER', 3, 2, '', '','N', 'admin', CURRENT_TIMESTAMP(6), '', null, '普通的用户', null); +INSERT IGNORE INTO sys_dict_data VALUES (7, 4, 'GUEST', 4, 2, '', '','N', 'admin', CURRENT_TIMESTAMP(6), '', null, '系统访客,不需要认证,最小权限', null); + +# INSERT IGNORE INTO sys_dict_data VALUES (4, 1, '正常', '0', 'sys_common_status', '', '','Y', '0', 'admin', CURRENT_TIMESTAMP(6), '', null, 'UI 按钮资源', null); +# INSERT IGNORE INTO sys_dict_data VALUES (5, 2, '已锁定', '1', 'sys_common_status', '', '','N', '0', 'admin', CURRENT_TIMESTAMP(6), '', null, 'UI 按钮资源', null); +# INSERT IGNORE INTO sys_dict_data VALUES (6, 3, '已禁用', '2', 'sys_common_status', '', '','N', '0', 'admin', CURRENT_TIMESTAMP(6), '', null, 'UI 按钮资源', null); +# INSERT IGNORE INTO sys_dict_data VALUES (7, 4, '已删除', '3', 'sys_common_status', '', '','N', '0', 'admin', CURRENT_TIMESTAMP(6), '', null, 'UI 按钮资源', null); + +-- 开启外键约束检查 +set foreign_key_checks = 1; \ No newline at end of file diff --git a/cs-database/src/main/resources/rbac/schema.sql b/cs-database/src/main/resources/rbac/schema.sql new file mode 100644 index 0000000..c0628d9 --- /dev/null +++ b/cs-database/src/main/resources/rbac/schema.sql @@ -0,0 +1,220 @@ +/* + Navicat Premium Data Transfer + + Source Server : 腾讯云 + Source Server Type : MySQL + Source Server Version : 80033 + Source Host : 101.35.234.160:32306 + Source Schema : admin3 + + Target Server Type : MySQL + Target Server Version : 80033 + File Encoding : 65001 + + Date: 07/12/2023 16:34:32 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for role +-- ---------------------------- +CREATE TABLE IF NOT EXISTS `rbac_role` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id', + `available` bit(1) NULL DEFAULT NULL COMMENT '是否有效', + `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '权限描述', + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '权限名称', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `UK_8sewwnpamngi6b1dwaa88askk` (`name` ASC) USING BTREE +) ENGINE = InnoDB + AUTO_INCREMENT = 5 + CHARACTER SET = utf8mb4 + COLLATE = utf8mb4_general_ci + ROW_FORMAT = Dynamic COMMENT '权限'; + +-- ---------------------------- +-- Table structure for role_resource +-- ---------------------------- +CREATE TABLE IF NOT EXISTS `rbac_role_resource` +( + `role_id` bigint NOT NULL COMMENT '权限id', + `resource_id` bigint NOT NULL COMMENT '权限资源id', + `authorize` bit(1) NULL DEFAULT NULL COMMENT '0: deny, 1: allow', + PRIMARY KEY (`resource_id`, `role_id`) USING BTREE, + INDEX `FKh8lunkrwoyio367ec8y12bis1` (`role_id` ASC) USING BTREE, + CONSTRAINT `FKh8lunkrwoyio367ec8y12bis1` FOREIGN KEY (`role_id`) REFERENCES `rbac_role` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT, + CONSTRAINT `FKr2orp5em3dob6f299ra9oyexr` FOREIGN KEY (`resource_id`) REFERENCES `rbac_resource_data` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE = InnoDB + CHARACTER SET = utf8mb4 + COLLATE = utf8mb4_general_ci + ROW_FORMAT = Dynamic COMMENT '权限资源'; + +-- ---------------------------- +-- Table structure for user +-- ---------------------------- +CREATE TABLE IF NOT EXISTS `rbac_user` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id', + `uid` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL UNIQUE COMMENT '用户UUID', + `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名', + `created_time` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间', + `gender` bigint NOT NULL COMMENT '创建用户', + `role_id` bigint(20) NOT NULL COMMENT '用户权限组', + `delete_time` datetime NULL DEFAULT NULL COMMENT '逻辑删除标记', + PRIMARY KEY (`id`) USING BTREE, + INDEX `fk_role_id` (`role_id`) USING BTREE, + CONSTRAINT `fk_role_id` FOREIGN KEY (`role_id`) REFERENCES `rbac_role` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE = InnoDB + AUTO_INCREMENT = 1000 + CHARACTER SET = utf8mb4 + COLLATE = utf8mb4_general_ci + ROW_FORMAT = Dynamic COMMENT '用户表'; + +-- ---------------------------- +-- Table structure for user_credential +-- ---------------------------- +CREATE TABLE IF NOT EXISTS `rbac_user_credential` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id', + `credential` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户密码', + `identifier` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户标识', + `identity_type` smallint NULL DEFAULT NULL COMMENT '登录类型', + `user_id` bigint NOT NULL DEFAULT -1 COMMENT '用户id', + `state` smallint NOT NULL COMMENT '当前状态(CommonStatus):0-->正常,1-->锁定,2-->禁用,3-->删除', + `error_cnt` smallint NOT NULL DEFAULT 0 COMMENT '密码错误次数', + `lock_at` datetime(6) NULL COMMENT '账户锁定时间', + `delete_time` datetime NULL DEFAULT NULL COMMENT '逻辑删除标记', + PRIMARY KEY (`id`) USING BTREE, + INDEX `FK6y499rs9ocqqa3kdpu2f32m86` (`user_id` ASC) USING BTREE, + CONSTRAINT `FK6y499rs9ocqqa3kdpu2f32m86` FOREIGN KEY (`user_id`) REFERENCES `rbac_user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE = InnoDB + AUTO_INCREMENT = 1000 + CHARACTER SET = utf8mb4 + COLLATE = utf8mb4_general_ci + ROW_FORMAT = Dynamic COMMENT '用户认证'; + +-- ---------------------------- +-- Table structure for user_role +-- ---------------------------- +-- DROP TABLE IF EXISTS `user_role`; +-- CREATE TABLE `user_role` +-- ( +-- `user_id` bigint NOT NULL COMMENT '用户id', +-- `role_id` bigint NOT NULL COMMENT '权限id', +-- PRIMARY KEY (`role_id`, `user_id`) USING BTREE, +-- INDEX `FKfgsgxvihks805qcq8sq26ab7c` (`user_id` ASC) USING BTREE, +-- CONSTRAINT `FKa68196081fvovjhkek5m97n3y` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT, +-- CONSTRAINT `FKfgsgxvihks805qcq8sq26ab7c` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT +-- ) ENGINE = InnoDB +-- CHARACTER SET = utf8mb4 +-- COLLATE = utf8mb4_general_ci +-- ROW_FORMAT = Dynamic COMMENT '用户权限'; + +-- ---------------------------- +-- Table structure for resource +-- ---------------------------- +CREATE TABLE IF NOT EXISTS `rbac_resource_data` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id', + `uid` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL UNIQUE COMMENT '资源UUID', + `path` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '资源URL', + `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '资源名称', + `http_method` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'GET' COMMENT '资源访问 HTTP 方法 GET/POST/DELETE/...', + `type_id` smallint NOT NULL COMMENT '资源类型(resource_type):0-->路由,1-->菜单,2-->按钮,...', + CONSTRAINT `FKa68196081fvovjhkekresourcetype` FOREIGN KEY (`type_id`) REFERENCES `rbac_resource_type` (`type_id`) ON DELETE RESTRICT ON UPDATE RESTRICT, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB + AUTO_INCREMENT = 1000 + CHARACTER SET = utf8mb4 + COLLATE = utf8mb4_general_ci + ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for resource +-- ---------------------------- +CREATE TABLE IF NOT EXISTS `rbac_resource_type` +( + `type_id` smallint NOT NULL COMMENT '资源类型:0-->路由,1-->菜单,2-->按钮,...', + `name` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '资源名称', + PRIMARY KEY (`type_id`) USING BTREE +) ENGINE = InnoDB + AUTO_INCREMENT = 1000 + CHARACTER SET = utf8mb4 + COLLATE = utf8mb4_general_ci + ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for stored_event +-- ---------------------------- +CREATE TABLE IF NOT EXISTS `sys_operation_log` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id', + `uid` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL UNIQUE COMMENT '操作日志UUID', + `module` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '操作模块', + `operation_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '操作类型', + `operation_status` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '操作状态', + `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '操作说明', + `request_ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '请求来源 IP 地址', + `call_function` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '请求接口', + `http_method` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'HTTP 请求类型', + `http_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '请求URI', + `transmit_delay` bigint NULL DEFAULT NULL COMMENT '传输延时(ms)', + `expend_time` bigint NULL DEFAULT NULL COMMENT '响应时间(ms)', + `user_id` bigint NULL DEFAULT NULL COMMENT '操作用户id', + `operation_time` datetime(6) NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '操作时间', + `request_headers` varchar(4095) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'HTTP 请求头所有参数', + `request` varchar(4095) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '操作请求参数', + `result` varchar(4095) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '操作返回结果', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB + AUTO_INCREMENT = 1 + CHARACTER SET = utf8mb4 + COLLATE = utf8mb4_general_ci + ROW_FORMAT = Dynamic COMMENT '系统操作日志'; + +CREATE TABLE IF NOT EXISTS `sys_dict_data` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '字典编码', + `dict_sort` int(4) NULL DEFAULT 0 COMMENT '字典排序', + `dict_label` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '字典标签', + `dict_value` smallint NOT NULL COMMENT '字典键值', + `type_id` bigint(20) NOT NULL COMMENT '字典类型', + `css_class` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '样式属性(其他样式扩展)', + `list_class` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '表格回显样式', + `is_default` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT 'N' COMMENT '是否默认(Y是 N否)', + `create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime(6) NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `delete_time` datetime NULL DEFAULT NULL COMMENT '逻辑删除标记', + CONSTRAINT `FKa68196081fvovjhkekdicttype` FOREIGN KEY (`type_id`) REFERENCES `sys_dict_type` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB + AUTO_INCREMENT = 100 + CHARACTER SET = utf8mb4 + COLLATE = utf8mb4_general_ci COMMENT = '字典数据表' + ROW_FORMAT = Dynamic; + +CREATE TABLE IF NOT EXISTS `sys_dict_type` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '字典主键', + `dict_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '字典名称', + `dict_type` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '字典类型', + `create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime(6) NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime(6) NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `delete_time` datetime NULL DEFAULT NULL COMMENT '逻辑删除标记', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `dict_type` (`dict_type`) USING BTREE +) ENGINE = InnoDB + AUTO_INCREMENT = 100 + CHARACTER SET = utf8mb4 + COLLATE = utf8mb4_general_ci COMMENT = '字典类型表' + ROW_FORMAT = Dynamic; + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/cs-database/src/test/java/com/cf/cs/database/CsDatabaseApplicationTests.java b/cs-database/src/test/java/com/cf/cs/database/CsDatabaseApplicationTests.java new file mode 100644 index 0000000..5211df4 --- /dev/null +++ b/cs-database/src/test/java/com/cf/cs/database/CsDatabaseApplicationTests.java @@ -0,0 +1,13 @@ +package com.cf.cs.database; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class CsDatabaseApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/cs-protocol/pom.xml b/cs-protocol/pom.xml new file mode 100644 index 0000000..e345586 --- /dev/null +++ b/cs-protocol/pom.xml @@ -0,0 +1,43 @@ + + + 4.0.0 + + com.cf.cs + IntegrateService + 0.0.1-dev + + + cs-protocol + cs-protocol + cs-protocol + jar + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-test + test + + + com.cf.cs + cs-base + ${cs-package.version} + compile + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/cs-protocol/src/main/java/com/cf/cs/protocol/CsProtocolApplication.java b/cs-protocol/src/main/java/com/cf/cs/protocol/CsProtocolApplication.java new file mode 100644 index 0000000..5e71f5d --- /dev/null +++ b/cs-protocol/src/main/java/com/cf/cs/protocol/CsProtocolApplication.java @@ -0,0 +1,23 @@ +package com.cf.cs.protocol; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * The type Cs protocol application. + * + * @author xajhuang @163.com + */ +@SpringBootApplication +public class CsProtocolApplication { + + /** + * The entry point of application. + * + * @param args the input arguments + */ + public static void main(String[] args) { + SpringApplication.run(CsProtocolApplication.class, args); + } + +} diff --git a/cs-protocol/src/main/java/com/cf/cs/protocol/config/ProtocolConfigure.java b/cs-protocol/src/main/java/com/cf/cs/protocol/config/ProtocolConfigure.java new file mode 100644 index 0000000..4d84c41 --- /dev/null +++ b/cs-protocol/src/main/java/com/cf/cs/protocol/config/ProtocolConfigure.java @@ -0,0 +1,56 @@ +package com.cf.cs.protocol.config; + +import jakarta.annotation.PostConstruct; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import java.util.Optional; + +/** + * The type Protocol configure. + * + * @author xajhuang @163.com + */ +@Data +@ConfigurationProperties(prefix = "protocol") +@Configuration +@Slf4j +public class ProtocolConfigure { + /** + * The constant CHECK_TIMESTAMP. + */ + public static boolean CHECK_TIMESTAMP; + /** + * The Timeout of seconds. + */ + public static long TIMEOUT_OF_SECONDS; + /** + * The Security protocol type. + */ + public static int SECURITY_PROTOCOL_TYPE; + + private Boolean checkTimestamp; + private Integer timeoutOfSeconds; + private Integer cryptoType; + private String cryptoKey; + + @PostConstruct + private void initGlobalValue() { + log.info("Current: checkTimestamp = {}, timeoutOfSeconds = {}", checkTimestamp, timeoutOfSeconds); + + ProtocolConfigure.CHECK_TIMESTAMP = Optional.ofNullable(checkTimestamp).orElse(false); + ProtocolConfigure.TIMEOUT_OF_SECONDS = Optional.ofNullable(timeoutOfSeconds).orElse(30); + ProtocolConfigure.SECURITY_PROTOCOL_TYPE = Optional.ofNullable(cryptoType).orElse(0); + } + + /** + * Gets timeout of millisecond. + * + * @return the timeout of millisecond + */ + public Long getTimeoutOfMillisecond() { + return (long) (timeoutOfSeconds * 1000); + } +} diff --git a/cs-protocol/src/main/java/com/cf/cs/protocol/pojo/base/BaseProtocol.java b/cs-protocol/src/main/java/com/cf/cs/protocol/pojo/base/BaseProtocol.java new file mode 100644 index 0000000..7202253 --- /dev/null +++ b/cs-protocol/src/main/java/com/cf/cs/protocol/pojo/base/BaseProtocol.java @@ -0,0 +1,46 @@ +package com.cf.cs.protocol.pojo.base; + +import com.cf.cs.protocol.validation.group.ValidGroups; +import com.cf.cs.protocol.validation.valids.ValidProtocolTimestamp; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Range; + +import java.io.Serial; +import java.io.Serializable; + +/** + * The type Base protocol. + * + * @param the type parameter + * @author xajhuang @163.com + */ +@Data +@NoArgsConstructor +@JsonPropertyOrder({"ver", "cryptoType", "timeStamp", "msgContent"}) +@JsonIgnoreProperties +@JsonInclude(JsonInclude.Include.NON_NULL) +public class BaseProtocol implements Serializable { + @Serial + private static final long serialVersionUID = -32326523643641L; + + @NotNull(message = "ver 字段不能为空", groups = ValidGroups.ProtocolCommonValid.class) + @Range(min = 1, max = 9999, message = "ver 字段最小值为 1", groups = ValidGroups.ProtocolCommonValid.class) + private Integer ver; + + @NotNull(message = "cryptoType 字段不能为空", groups = ValidGroups.ProtocolCommonValid.class) + @Range(min = 0, max = 4, message = "cryptoType 字段取值为 [0, 4]", groups = ValidGroups.ProtocolCommonValid.class) + private Integer cryptoType; + + @NotNull(message = "timeStamp 字段不能为空", groups = ValidGroups.ProtocolCommonValid.class) + @ValidProtocolTimestamp(message = "timeStamp 字段值与当前时间差不能大于超时配置", groups = ValidGroups.ProtocolCommonValid.class) + private Long timeStamp; + + @Valid + private T msgContent; +} diff --git a/cs-protocol/src/main/java/com/cf/cs/protocol/pojo/po/BaseRespStatus.java b/cs-protocol/src/main/java/com/cf/cs/protocol/pojo/po/BaseRespStatus.java new file mode 100644 index 0000000..c4c5edd --- /dev/null +++ b/cs-protocol/src/main/java/com/cf/cs/protocol/pojo/po/BaseRespStatus.java @@ -0,0 +1,19 @@ +package com.cf.cs.protocol.pojo.po; + +import com.cf.cs.base.common.ErrorCode; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * The type Base resp status. + * + * @author xajhuang @163.com + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class BaseRespStatus { + private Integer status = ErrorCode.ERR_OK.getCode(); + private String[] message = new String[] {ErrorCode.ERR_OK.getDescription()}; +} diff --git a/cs-protocol/src/main/java/com/cf/cs/protocol/pojo/po/VersionInfo.java b/cs-protocol/src/main/java/com/cf/cs/protocol/pojo/po/VersionInfo.java new file mode 100644 index 0000000..728eaa6 --- /dev/null +++ b/cs-protocol/src/main/java/com/cf/cs/protocol/pojo/po/VersionInfo.java @@ -0,0 +1,24 @@ +package com.cf.cs.protocol.pojo.po; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * The type Version info. + * + * @author xajhuang @163.com + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class VersionInfo { + private String commitId; + private String commitDescribe; + private String commitTime; + private String tagName; + private String buildTime; + private String gitBranch; +} diff --git a/cs-protocol/src/main/java/com/cf/cs/protocol/pojo/vo/ProtocolResp.java b/cs-protocol/src/main/java/com/cf/cs/protocol/pojo/vo/ProtocolResp.java new file mode 100644 index 0000000..2378065 --- /dev/null +++ b/cs-protocol/src/main/java/com/cf/cs/protocol/pojo/vo/ProtocolResp.java @@ -0,0 +1,90 @@ +package com.cf.cs.protocol.pojo.vo; + +import com.cf.cs.base.common.CommonEnumHandler; +import com.cf.cs.base.common.ConstValue; +import com.cf.cs.base.common.ErrorCode; +import com.cf.cs.protocol.config.ProtocolConfigure; +import com.cf.cs.protocol.pojo.base.BaseProtocol; +import com.cf.cs.protocol.pojo.po.BaseRespStatus; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * The type Protocol resp. + * + * @param the type parameter + * @author xajhuang @163.com + */ +@Slf4j +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +@JsonPropertyOrder({"ver", "cryptoType", "timeStamp", "code", "msgContent"}) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ProtocolResp extends BaseProtocol { + private Integer code; + + private static ProtocolResp result(ErrorCode err, Integer httpCode, T respMsg) { + ProtocolResp resp = new ProtocolResp<>(); + + resp.setVer(ConstValue.Protocol.VERSION); + resp.setCode(httpCode); + resp.setCryptoType(ProtocolConfigure.SECURITY_PROTOCOL_TYPE); + resp.setTimeStamp(System.currentTimeMillis()); + resp.setMsgContent(respMsg); + return resp; + } + + /** + * Result protocol resp. + * + * @param the type parameter + * @param err the err + * @param respMsg the resp msg + * @return the protocol resp + */ + public static ProtocolResp result(ErrorCode err, T respMsg) { + return result(err, err.getHttpCode(), respMsg); + } + + /** + * Result protocol resp. + * + * @param err the err + * @return the protocol resp + */ + public static ProtocolResp result(ErrorCode err) { + BaseRespStatus rspMsg = new BaseRespStatus(err.getCode(), new String[] {err.getDescription()}); + return result(err, err.getHttpCode(), rspMsg); + } + + /** + * Result protocol resp. + * + * @param the type parameter + * @param respMsg the resp msg + * @return the protocol resp + */ + public static ProtocolResp result(T respMsg) { + return result(CommonEnumHandler.codeOf(ErrorCode.class, respMsg.getStatus()), respMsg); + } + + /** + * Result protocol resp. + * + * @param errCode the err code + * @param httpCode the http code + * @param message the message + * @return the protocol resp + */ + public static ProtocolResp result(ErrorCode errCode, Integer httpCode, String[] message) { + BaseRespStatus rspMsg = new BaseRespStatus(errCode.getCode(), message); + return result(errCode, httpCode, rspMsg); + } +} diff --git a/cs-protocol/src/main/java/com/cf/cs/protocol/pojo/vo/VersionResp.java b/cs-protocol/src/main/java/com/cf/cs/protocol/pojo/vo/VersionResp.java new file mode 100644 index 0000000..fa525b0 --- /dev/null +++ b/cs-protocol/src/main/java/com/cf/cs/protocol/pojo/vo/VersionResp.java @@ -0,0 +1,25 @@ +package com.cf.cs.protocol.pojo.vo; + +import com.cf.cs.protocol.pojo.po.BaseRespStatus; +import com.cf.cs.protocol.pojo.po.VersionInfo; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * The type Version resp. + * + * @author xajhuang @163.com + */ +@EqualsAndHashCode(callSuper = true) +@Data +@JsonPropertyOrder({"version", "status", "message"}) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class VersionResp extends BaseRespStatus { + private VersionInfo version; +} diff --git a/cs-protocol/src/main/java/com/cf/cs/protocol/validation/group/JsonViewGroups.java b/cs-protocol/src/main/java/com/cf/cs/protocol/validation/group/JsonViewGroups.java new file mode 100644 index 0000000..1796770 --- /dev/null +++ b/cs-protocol/src/main/java/com/cf/cs/protocol/validation/group/JsonViewGroups.java @@ -0,0 +1,29 @@ +package com.cf.cs.protocol.validation.group; + +/** + * The type Json view groups. + * + * @author xajhuang @163.com + */ +public class JsonViewGroups { + /** + * The type Common view. + * + * @author xajhuang @163.com + */ + public static class CommonView {} + + /** + * The type Dict content response. + * + * @author xajhuang @163.com + */ + public static class DictContentResponse extends CommonView {} + + /** + * The type Dict content request. + * + * @author xajhuang @163.com + */ + public static class DictContentRequest extends CommonView {} +} diff --git a/cs-protocol/src/main/java/com/cf/cs/protocol/validation/group/ValidGroups.java b/cs-protocol/src/main/java/com/cf/cs/protocol/validation/group/ValidGroups.java new file mode 100644 index 0000000..6f09f64 --- /dev/null +++ b/cs-protocol/src/main/java/com/cf/cs/protocol/validation/group/ValidGroups.java @@ -0,0 +1,105 @@ +package com.cf.cs.protocol.validation.group; + +/** + * The interface Valid groups. + * + * @author xajhuang @163.com + */ +public interface ValidGroups { + + /** + * The interface Protocol common valid. + * + * @author xajhuang @163.com + */ + interface ProtocolCommonValid { + } + + /** + * The interface Base protocol valid. + * + * @author xajhuang @163.com + */ + interface BaseProtocolValid extends ProtocolCommonValid { + } + + /** + * The interface Base paged req valid. + * + * @author xajhuang @163.com + */ + interface BasePagedReqValid extends BaseProtocolValid { + } + + /** + * The interface Login req valid. + * + * @author xajhuang @163.com + */ + interface LoginReqValid extends BaseProtocolValid { + } + + /** + * The interface Logout req valid. + * + * @author + */ + interface LogoutReqValid extends BaseProtocolValid { + } + + /** + * The interface Operation log req valid. + * + * @author xajhuang @163.com + */ + interface OperationLogReqValid extends BaseProtocolValid { + } + + /** + * The interface User id req valid. + * + * @author xajhuang @163.com + */ + interface UserIdReqValid extends BaseProtocolValid { + } + + /** + * The interface User req valid. + * + * @author xajhuang @163.com + */ + interface UserReqValid extends BaseProtocolValid { + } + + /** + * The interface Resource req valid. + * + * @author xajhuang @163.com + */ + interface ResourceReqValid extends BaseProtocolValid { + } + + /** + * The interface Resource info valid. + * + * @author xajhuang @163.com + */ + interface ResourceInfoValid extends BaseProtocolValid { + } + + /** + * The interface Dict req valid. + * + * @author xajhuang @163.com + */ + interface DictReqValid extends BaseProtocolValid { + } + + /** + * The interface Dict req content valid. + * + * @author xajhuang @163.com + */ + interface DictReqContentValid extends BaseProtocolValid { + } +} diff --git a/cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/UUID.java b/cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/UUID.java new file mode 100644 index 0000000..c7e4e05 --- /dev/null +++ b/cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/UUID.java @@ -0,0 +1,42 @@ +package com.cf.cs.protocol.validation.valids; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.constraints.Pattern; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * The interface Uuid. + * + * @author xajhuang @163.com + */ +@Target(ElementType.FIELD) +@Constraint(validatedBy = {}) +@Retention(RetentionPolicy.RUNTIME) +@Pattern(regexp = "^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$") +public @interface UUID { + /** + * Message string. + * + * @return the string + */ + String message() default "{invalid.uuid}"; + + /** + * Groups class [ ]. + * + * @return the class [ ] + */ + Class[] groups() default {}; + + /** + * Payload class [ ]. + * + * @return the class [ ] + */ + Class[] payload() default {}; +} diff --git a/cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/ValidHttpMethod.java b/cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/ValidHttpMethod.java new file mode 100644 index 0000000..f5dd682 --- /dev/null +++ b/cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/ValidHttpMethod.java @@ -0,0 +1,43 @@ +package com.cf.cs.protocol.validation.valids; + +import com.cf.cs.protocol.validation.valids.impl.ValidHttpMethodImpl; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * The interface Valid http method. + * + * @author xajhuang @163.com + */ +@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Constraint(validatedBy = {ValidHttpMethodImpl.class}) +public @interface ValidHttpMethod { + /** + * Message string. + * + * @return the string + */ + String message() default ""; + + /** + * Groups class [ ]. + * + * @return the class [ ] + */ + Class[] groups() default {}; + + /** + * Payload class [ ]. + * + * @return the class [ ] + */ + Class[] payload() default {}; +} diff --git a/cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/ValidPageSize.java b/cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/ValidPageSize.java new file mode 100644 index 0000000..d5a208b --- /dev/null +++ b/cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/ValidPageSize.java @@ -0,0 +1,43 @@ +package com.cf.cs.protocol.validation.valids; + +import com.cf.cs.protocol.validation.valids.impl.ValidPageSizeImpl; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * The interface Valid page size. + * + * @author xajhuang @163.com + */ +@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Constraint(validatedBy = {ValidPageSizeImpl.class}) +public @interface ValidPageSize { + /** + * Message string. + * + * @return the string + */ + String message(); + + /** + * Groups class [ ]. + * + * @return the class [ ] + */ + Class[] groups() default {}; + + /** + * Payload class [ ]. + * + * @return the class [ ] + */ + Class[] payload() default {}; +} diff --git a/cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/ValidProtocolTimestamp.java b/cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/ValidProtocolTimestamp.java new file mode 100644 index 0000000..7567ad7 --- /dev/null +++ b/cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/ValidProtocolTimestamp.java @@ -0,0 +1,43 @@ +package com.cf.cs.protocol.validation.valids; + +import com.cf.cs.protocol.validation.valids.impl.ValidProtocolTimestampImpl; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * The interface Valid protocol timestamp. + * + * @author xajhuang @163.com + */ +@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Constraint(validatedBy = {ValidProtocolTimestampImpl.class}) +public @interface ValidProtocolTimestamp { + /** + * Message string. + * + * @return the string + */ + String message(); + + /** + * Groups class [ ]. + * + * @return the class [ ] + */ + Class[] groups() default {}; + + /** + * Payload class [ ]. + * + * @return the class [ ] + */ + Class[] payload() default {}; +} diff --git a/cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/impl/ValidHttpMethodImpl.java b/cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/impl/ValidHttpMethodImpl.java new file mode 100644 index 0000000..7f7dcba --- /dev/null +++ b/cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/impl/ValidHttpMethodImpl.java @@ -0,0 +1,41 @@ +package com.cf.cs.protocol.validation.valids.impl; + +import com.cf.cs.protocol.validation.valids.ValidHttpMethod; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import org.springframework.web.bind.annotation.RequestMethod; + +import java.util.List; + +/** + * The type Valid http method. + * + * @author xajhuang @163.com + */ +public class ValidHttpMethodImpl implements ConstraintValidator> { + @Override + public void initialize(ValidHttpMethod constraintAnnotation) { + + ConstraintValidator.super.initialize(constraintAnnotation); + } + + @Override + public boolean isValid(List strings, ConstraintValidatorContext context) { + StringBuilder errMsg = new StringBuilder(); + + strings.forEach(k -> { + if (RequestMethod.resolve(k.toUpperCase()) == null) { + errMsg.append("[") + .append(k) + .append("]: 不是合法的 HTTP 请求方法"); + } + }); + + if (!errMsg.isEmpty()) { + context.disableDefaultConstraintViolation(); + context.buildConstraintViolationWithTemplate(errMsg.toString()).addConstraintViolation(); + return false; + } + return true; + } +} diff --git a/cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/impl/ValidPageSizeImpl.java b/cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/impl/ValidPageSizeImpl.java new file mode 100644 index 0000000..7dd00a7 --- /dev/null +++ b/cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/impl/ValidPageSizeImpl.java @@ -0,0 +1,22 @@ +package com.cf.cs.protocol.validation.valids.impl; + +import com.cf.cs.protocol.validation.valids.ValidPageSize; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; + +/** + * The type Valid page size. + * + * @author xajhuang @163.com + */ +public class ValidPageSizeImpl implements ConstraintValidator { + @Override + public void initialize(ValidPageSize constraintAnnotation) { + ConstraintValidator.super.initialize(constraintAnnotation); + } + + @Override + public boolean isValid(Long pageSize, ConstraintValidatorContext constraintValidatorContext) { + return pageSize % 5 == 0; + } +} diff --git a/cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/impl/ValidProtocolTimestampImpl.java b/cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/impl/ValidProtocolTimestampImpl.java new file mode 100644 index 0000000..95f9973 --- /dev/null +++ b/cs-protocol/src/main/java/com/cf/cs/protocol/validation/valids/impl/ValidProtocolTimestampImpl.java @@ -0,0 +1,55 @@ +package com.cf.cs.protocol.validation.valids.impl; + + +import com.cf.cs.protocol.config.ProtocolConfigure; +import com.cf.cs.protocol.validation.valids.ValidProtocolTimestamp; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; + +import java.text.SimpleDateFormat; + + +/** + * The type Valid protocol timestamp. + * + * @author xajhuang @163.com + */ +public class ValidProtocolTimestampImpl implements ConstraintValidator { + + @Override + public void initialize(ValidProtocolTimestamp constraintAnnotation) { + ConstraintValidator.super.initialize(constraintAnnotation); + } + + @Override + public boolean isValid(Long timeStamp, ConstraintValidatorContext constraintValidatorContext) { + + if (!ProtocolConfigure.CHECK_TIMESTAMP) { + return true; + } + + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + String date = format.format(timeStamp); + String current = format.format(System.currentTimeMillis()); + + + if (timeStamp > System.currentTimeMillis()) { + String errMsg = String.format("请求时间[%s] 大于当前服务器时间 [%s]", date, current); + //禁用默认的message的值 + constraintValidatorContext.disableDefaultConstraintViolation(); + //重新添加错误提示语句 + constraintValidatorContext.buildConstraintViolationWithTemplate(errMsg).addConstraintViolation(); + return false; + } else if (System.currentTimeMillis() - timeStamp > ProtocolConfigure.TIMEOUT_OF_SECONDS * 1000L) { + String errMsg = String.format("请求时间[%s] 延时超过当前服务器时间[%s] 允许范围 %d(S)", date, current, + ProtocolConfigure.TIMEOUT_OF_SECONDS); + //禁用默认的message的值 + constraintValidatorContext.disableDefaultConstraintViolation(); + //重新添加错误提示语句 + constraintValidatorContext.buildConstraintViolationWithTemplate(errMsg).addConstraintViolation(); + return false; + } + + return true; + } +} diff --git a/cs-protocol/src/test/java/com/cf/cs/protocol/CsProtocolApplicationTests.java b/cs-protocol/src/test/java/com/cf/cs/protocol/CsProtocolApplicationTests.java new file mode 100644 index 0000000..987a8e8 --- /dev/null +++ b/cs-protocol/src/test/java/com/cf/cs/protocol/CsProtocolApplicationTests.java @@ -0,0 +1,13 @@ +package com.cf.cs.protocol; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class CsProtocolApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/cs-restful/pom.xml b/cs-restful/pom.xml index 328f631..0688c5d 100644 --- a/cs-restful/pom.xml +++ b/cs-restful/pom.xml @@ -21,13 +21,22 @@ org.springframework.boot spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + + - org.springframework.boot spring-boot-starter-test test + + org.springframework.boot + spring-boot-starter-undertow + org.springdoc @@ -40,6 +49,30 @@ 2.3.0 + + com.cf.cs + cs-database + ${cs-package.version} + compile + + + com.cf.cs + cs-protocol + ${cs-package.version} + compile + + + com.cf.cs + cs-crypto + ${cs-package.version} + compile + + + com.cf.cs + cs-services + ${cs-package.version} + compile + com.cf.cs cs-web diff --git a/cs-restful/src/main/java/com/cf/cs/restful/CsRestfulApplication.java b/cs-restful/src/main/java/com/cf/cs/restful/CsRestfulApplication.java index 65a6770..e07a4c6 100644 --- a/cs-restful/src/main/java/com/cf/cs/restful/CsRestfulApplication.java +++ b/cs-restful/src/main/java/com/cf/cs/restful/CsRestfulApplication.java @@ -8,7 +8,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; * * @author xajhuang @163.com */ -@SpringBootApplication(scanBasePackages = {"com.cf.cs.base", "com.cf.cs.restful", "com.cf.cs.web"}) +@SpringBootApplication(scanBasePackages = {"com.cf.cs.base", "com.cf.cs.database", "com.cf.cs.protocol", + "com.cf.cs.services", "com.cf.cs.restful", "com.cf.cs.web"}) public class CsRestfulApplication { /** diff --git a/cs-restful/src/main/java/com/cf/cs/restful/controller/CommonFrameworkApi.java b/cs-restful/src/main/java/com/cf/cs/restful/controller/CommonFrameworkApi.java new file mode 100644 index 0000000..229cf61 --- /dev/null +++ b/cs-restful/src/main/java/com/cf/cs/restful/controller/CommonFrameworkApi.java @@ -0,0 +1,62 @@ +package com.cf.cs.restful.controller; + +import com.cf.cs.crypto.annotation.DecryptionProtocol; +import com.cf.cs.crypto.annotation.EncryptionProtocol; +import com.cf.cs.protocol.pojo.po.BaseRespStatus; +import com.cf.cs.protocol.pojo.po.VersionInfo; +import com.cf.cs.protocol.pojo.vo.ProtocolResp; +import com.cf.cs.protocol.pojo.vo.VersionResp; +import com.cf.cs.base.annotation.OperationLogAnnotation; +import com.cf.cs.web.configure.ProjectGitVersionInfo; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@Slf4j +@Tag(name = "通用接口") +@RequestMapping(value = "/api") +public class CommonFrameworkApi { + @Resource + private ProjectGitVersionInfo prgVer; + + @EncryptionProtocol + @DecryptionProtocol + @PostMapping("/version") + @ResponseBody + @OperationLogAnnotation(OperationModule = "通用模块", OperationType = "读取", OperationDesc = "获取当前系统版本信息") + public ProtocolResp getVersion() { + return ProtocolResp.result(VersionResp.builder() + .version(VersionInfo.builder() + .commitId(prgVer.getCommitId()) + .commitDescribe(prgVer.getCommitDescribe()) + .commitTime(prgVer.getCommitTime()) + .tagName(prgVer.getTagName()) + .buildTime(prgVer.getBuildTime()) + .gitBranch(prgVer.getGitBranch()) + .build()) + .build()); + } + + @GetMapping("/version") + @ResponseBody + @EncryptionProtocol + @OperationLogAnnotation(OperationModule = "通用模块", OperationType = "读取", OperationDesc = "获取当前系统版本信息") + public ProtocolResp getVersionV2() { + return ProtocolResp.result(VersionResp.builder() + .version(VersionInfo.builder() + .commitId(prgVer.getCommitId()) + .commitDescribe(prgVer.getCommitDescribe()) + .commitTime(prgVer.getCommitTime()) + .tagName(prgVer.getTagName()) + .buildTime(prgVer.getBuildTime()) + .gitBranch(prgVer.getGitBranch()) + .build()) + .build()); + } +} diff --git a/cs-services/pom.xml b/cs-services/pom.xml new file mode 100644 index 0000000..0e6044c --- /dev/null +++ b/cs-services/pom.xml @@ -0,0 +1,38 @@ + + + 4.0.0 + + com.cf.cs + IntegrateService + 0.0.1-dev + + + cs-services + cs-services + cs-services + jar + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/cs-services/src/main/java/com/cf/cs/services/CsServicesApplication.java b/cs-services/src/main/java/com/cf/cs/services/CsServicesApplication.java new file mode 100644 index 0000000..f3b6d35 --- /dev/null +++ b/cs-services/src/main/java/com/cf/cs/services/CsServicesApplication.java @@ -0,0 +1,23 @@ +package com.cf.cs.services; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * The type Cs services application. + * + * @author xajhuang @163.com + */ +@SpringBootApplication +public class CsServicesApplication { + + /** + * The entry point of application. + * + * @param args the input arguments + */ + public static void main(String[] args) { + SpringApplication.run(CsServicesApplication.class, args); + } + +} diff --git a/cs-services/src/test/java/com/cf/cs/services/CsServicesApplicationTests.java b/cs-services/src/test/java/com/cf/cs/services/CsServicesApplicationTests.java new file mode 100644 index 0000000..fc96476 --- /dev/null +++ b/cs-services/src/test/java/com/cf/cs/services/CsServicesApplicationTests.java @@ -0,0 +1,13 @@ +package com.cf.cs.services; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class CsServicesApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/cs-web/pom.xml b/cs-web/pom.xml index 1e92245..8f98bc6 100644 --- a/cs-web/pom.xml +++ b/cs-web/pom.xml @@ -16,15 +16,9 @@ org.springframework.boot - spring-boot-starter-cache + spring-boot-starter-test + test - - - com.github.ben-manes.caffeine - caffeine - 3.1.8 - - com.cf.cs cs-base diff --git a/cs-web/src/main/java/com/cf/cs/web/interceptor/RequestBodyCacheWrapper.java b/cs-web/src/main/java/com/cf/cs/web/interceptor/RequestBodyCacheWrapper.java new file mode 100644 index 0000000..bb6d9ec --- /dev/null +++ b/cs-web/src/main/java/com/cf/cs/web/interceptor/RequestBodyCacheWrapper.java @@ -0,0 +1,109 @@ +package com.cf.cs.web.interceptor; + +import com.cf.cs.base.misc.ApiContextUtils; +import com.cf.cs.base.misc.HelperUtils; +import jakarta.servlet.ReadListener; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequestWrapper; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +/** + * The type Request body cache wrapper. + * + * @author xajhuang @163.com + */ +@Getter +@Slf4j +public class RequestBodyCacheWrapper extends HttpServletRequestWrapper { + private final Long reqTimeStamp = System.currentTimeMillis(); + private final Map headers = new HashMap<>(); + private String body; + + /** + * Instantiates a new Request body cache wrapper. + * + * @param request the request + * @throws IOException the io exception + */ + public RequestBodyCacheWrapper(HttpServletRequest request) throws IOException { + super(request); + + StringBuilder stringBuilder = new StringBuilder(); + BufferedReader bufferedReader = null; + try (InputStream inputStream = request.getInputStream()) { + if (inputStream != null) { + bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); + char[] charBuffer = new char[128]; + int bytesRead; + while ((bytesRead = bufferedReader.read(charBuffer)) > 0) { + stringBuilder.append(charBuffer, 0, bytesRead); + } + } + } catch (Exception e) { + log.error("RequestWrapper read error :{}", e.getMessage()); + } finally { + + if (bufferedReader != null) { + bufferedReader.close(); + } + } + + try { + Object obj = HelperUtils.jsonGetObject(stringBuilder.toString(), Object.class); + body = HelperUtils.getJson(obj); + + Enumeration enumeration = request.getHeaderNames(); + while (enumeration.hasMoreElements()) { + String name = enumeration.nextElement(); + String value = request.getHeader(name); + headers.put(name, value); + } + } catch (Exception e) { + body = ""; + } finally { + ApiContextUtils.setRequestInfo(body, reqTimeStamp); + } + } + + @Override + public ServletInputStream getInputStream() { + final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes()); + return new ServletInputStream() { + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) { + } + + @Override + public int read() { + return byteArrayInputStream.read(); + } + }; + } + + @Override + public BufferedReader getReader() { + return new BufferedReader(new InputStreamReader(this.getInputStream(), StandardCharsets.UTF_8)); + } +} diff --git a/cs-web/src/main/java/com/cf/cs/web/interceptor/RequestBodyFilter.java b/cs-web/src/main/java/com/cf/cs/web/interceptor/RequestBodyFilter.java new file mode 100644 index 0000000..a2a63d5 --- /dev/null +++ b/cs-web/src/main/java/com/cf/cs/web/interceptor/RequestBodyFilter.java @@ -0,0 +1,45 @@ +package com.cf.cs.web.interceptor; + +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.annotation.WebFilter; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.io.IOException; + +/** + * The type Request body filter. + * + * @author xajhuang @163.com + */ +@Component +@WebFilter(filterName = "RequestBodyFilter", urlPatterns = "/") +@Order(10000) +public class RequestBodyFilter implements Filter { + @Override + public void init(FilterConfig filterConfig) throws ServletException { + Filter.super.init(filterConfig); + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, + ServletException { + ServletRequest requestWrapper = null; + if (servletRequest instanceof HttpServletRequest) { + requestWrapper = new RequestBodyCacheWrapper((HttpServletRequest) servletRequest); + } + //获取请求中的流如何,将取出来的字符串,再次转换成流,然后把它放入到新request对象中 + // 在chain.doFiler方法中传递新的request对象 + if (null == requestWrapper) { + filterChain.doFilter(servletRequest, servletResponse); + } else { + filterChain.doFilter(requestWrapper, servletResponse); + } + } +} \ No newline at end of file diff --git a/cs-web/src/main/java/com/cf/cs/web/setup/SystemInitial.java b/cs-web/src/main/java/com/cf/cs/web/setup/SystemInitial.java index e4e7de4..b8e633e 100644 --- a/cs-web/src/main/java/com/cf/cs/web/setup/SystemInitial.java +++ b/cs-web/src/main/java/com/cf/cs/web/setup/SystemInitial.java @@ -1,6 +1,6 @@ package com.cf.cs.web.setup; -import com.cf.cs.web.configure.CommonConfigure; +import com.cf.cs.base.config.CommonConfigure; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; diff --git a/pom.xml b/pom.xml index 9e8d250..a10aa51 100644 --- a/pom.xml +++ b/pom.xml @@ -25,6 +25,9 @@ cs-base cs-crypto + cs-protocol + cs-database + cs-services cs-web cs-restful