diff --git a/sql/ruoyi-vue-pro.sql b/sql/ruoyi-vue-pro.sql index 2fbf683a5..080f33e6f 100644 --- a/sql/ruoyi-vue-pro.sql +++ b/sql/ruoyi-vue-pro.sql @@ -4824,4 +4824,18 @@ INSERT INTO `system_user_session` VALUES ('fe11c39cfc2740a992063bf05bd170f3', 1, INSERT INTO `system_user_session` VALUES ('ffe28d833fea4e76a0b2b6bcde9236c2', 1, 2, '2022-04-03 22:03:16', 'admin', '0:0:0:0:0:0:0:1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.83 Safari/537.36', NULL, '2022-04-02 22:03:16', NULL, '2022-04-03 14:21:23', b'1', 1); COMMIT; +CREATE TABLE `infra_data_source_config` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键编号', + `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '参数名称', + `url` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '数据源连接', + `username` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户名', + `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '密码', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='数据源配置表'; + SET FOREIGN_KEY_CHECKS = 1; diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 1c871cf32..14a4b1dfc 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -45,6 +45,7 @@ 7.1.0.M6 6.7.0 + 3.0.4 1.18.20 1.4.1.Final 5.6.1 @@ -428,6 +429,12 @@ ${revision} + + com.github.ulisesbocchio + jasypt-spring-boot-starter + ${jasypt-spring-boot-starter.version} + + cn.iocoder.boot yudao-spring-boot-starter-excel diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/DatabaseUtils.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/DatabaseUtils.java new file mode 100644 index 000000000..b282656c5 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/DatabaseUtils.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.framework.mybatis.core.util; + +import java.sql.Connection; +import java.sql.DriverManager; + +/** + * 数据库工具类 + * + * @author 芋道源码 + */ +public class DatabaseUtils { + + /** + * 判断连接是否正确 + * + * @param url 数据源连接 + * @param username 账号 + * @param password 密码 + * @return 是否正确 + */ + public static boolean isConnectionOK(String url, String username, String password) { + try (Connection ignored = DriverManager.getConnection(url, username, password)) { + return true; + } catch (Exception ex) { + return false; + } + } + +} diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java index 1528955f9..8dd1a991f 100644 --- a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java +++ b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java @@ -49,4 +49,8 @@ public interface ErrorCodeConstants { ErrorCode FILE_CONFIG_NOT_EXISTS = new ErrorCode(1001006000, "文件配置不存在"); ErrorCode FILE_CONFIG_DELETE_FAIL_MASTER = new ErrorCode(1001006001, "该文件配置不允许删除,原因:它是主配置,删除会导致无法上传文件"); + // ========== 数据源配置 1001007000 ========== + ErrorCode DATA_SOURCE_CONFIG_NOT_EXISTS = new ErrorCode(1001007000, "数据源配置不存在"); + ErrorCode DATA_SOURCE_CONFIG_NOT_OK = new ErrorCode(1001007001, "数据源配置不正确,无法进行连接"); + } diff --git a/yudao-module-infra/yudao-module-infra-biz/pom.xml b/yudao-module-infra/yudao-module-infra-biz/pom.xml index 5c4c16d43..cd30fd21e 100644 --- a/yudao-module-infra/yudao-module-infra-biz/pom.xml +++ b/yudao-module-infra/yudao-module-infra-biz/pom.xml @@ -79,6 +79,11 @@ + + com.github.ulisesbocchio + jasypt-spring-boot-starter + + cn.iocoder.boot yudao-spring-boot-starter-excel diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/DataSourceConfigController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/DataSourceConfigController.java new file mode 100755 index 000000000..6b535ae98 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/DataSourceConfigController.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.infra.controller.admin.db; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigRespVO; +import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO; +import cn.iocoder.yudao.module.infra.convert.db.DataSourceConfigConvert; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; +import cn.iocoder.yudao.module.infra.service.db.DataSourceConfigService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Api(tags = "管理后台 - 数据源配置") +@RestController +@RequestMapping("/infra/data-source-config") +@Validated +public class DataSourceConfigController { + + @Resource + private DataSourceConfigService dataSourceConfigService; + + @PostMapping("/create") + @ApiOperation("创建数据源配置") + @PreAuthorize("@ss.hasPermission('infra:data-source-config:create')") + public CommonResult createDataSourceConfig(@Valid @RequestBody DataSourceConfigCreateReqVO createReqVO) { + return success(dataSourceConfigService.createDataSourceConfig(createReqVO)); + } + + @PutMapping("/update") + @ApiOperation("更新数据源配置") + @PreAuthorize("@ss.hasPermission('infra:data-source-config:update')") + public CommonResult updateDataSourceConfig(@Valid @RequestBody DataSourceConfigUpdateReqVO updateReqVO) { + dataSourceConfigService.updateDataSourceConfig(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @ApiOperation("删除数据源配置") + @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) + @PreAuthorize("@ss.hasPermission('infra:data-source-config:delete')") + public CommonResult deleteDataSourceConfig(@RequestParam("id") Long id) { + dataSourceConfigService.deleteDataSourceConfig(id); + return success(true); + } + + @GetMapping("/get") + @ApiOperation("获得数据源配置") + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) + @PreAuthorize("@ss.hasPermission('infra:data-source-config:query')") + public CommonResult getDataSourceConfig(@RequestParam("id") Long id) { + DataSourceConfigDO dataSourceConfig = dataSourceConfigService.getDataSourceConfig(id); + return success(DataSourceConfigConvert.INSTANCE.convert(dataSourceConfig)); + } + + @GetMapping("/list") + @ApiOperation("获得数据源配置列表") + @PreAuthorize("@ss.hasPermission('infra:data-source-config:query')") + public CommonResult> getDataSourceConfigList() { + List list = dataSourceConfigService.getDataSourceConfigList(); + return success(DataSourceConfigConvert.INSTANCE.convertList(list)); + } + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/doc/DbDocController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/DatabaseDocController.java similarity index 98% rename from yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/doc/DbDocController.java rename to yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/DatabaseDocController.java index 83d9db798..eb35d4555 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/doc/DbDocController.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/DatabaseDocController.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.infra.controller.admin.doc; +package cn.iocoder.yudao.module.infra.controller.admin.db; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.IdUtil; @@ -30,7 +30,7 @@ import java.util.Arrays; @Api(tags = "管理后台 - 数据库文档") @RestController @RequestMapping("/infra/db-doc") -public class DbDocController { +public class DatabaseDocController { @Resource private DynamicDataSourceProperties dynamicDataSourceProperties; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigBaseVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigBaseVO.java new file mode 100755 index 000000000..ae3d97dce --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigBaseVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.infra.controller.admin.db.vo; + +import lombok.*; +import java.util.*; +import io.swagger.annotations.*; +import javax.validation.constraints.*; + +/** +* 数据源配置 Base VO,提供给添加、修改、详细的子 VO 使用 +* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 +*/ +@Data +public class DataSourceConfigBaseVO { + + @ApiModelProperty(value = "参数名称", required = true, example = "test") + @NotNull(message = "参数名称不能为空") + private String name; + + @ApiModelProperty(value = "数据源连接", required = true, example = "jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro") + @NotNull(message = "数据源连接不能为空") + private String url; + + @ApiModelProperty(value = "用户名", required = true, example = "root") + @NotNull(message = "用户名不能为空") + private String username; + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigCreateReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigCreateReqVO.java new file mode 100755 index 000000000..13085f9b1 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigCreateReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.infra.controller.admin.db.vo; + +import lombok.*; +import java.util.*; +import io.swagger.annotations.*; +import javax.validation.constraints.*; + +@ApiModel("管理后台 - 数据源配置创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class DataSourceConfigCreateReqVO extends DataSourceConfigBaseVO { + + @ApiModelProperty(value = "密码", required = true, example = "123456") + @NotNull(message = "密码不能为空") + private String password; + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigRespVO.java new file mode 100755 index 000000000..af63aa0dd --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigRespVO.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.infra.controller.admin.db.vo; + +import lombok.*; +import java.util.*; +import io.swagger.annotations.*; + +@ApiModel("管理后台 - 数据源配置 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class DataSourceConfigRespVO extends DataSourceConfigBaseVO { + + @ApiModelProperty(value = "主键编号", required = true, example = "1024") + private Integer id; + + @ApiModelProperty(value = "创建时间", required = true) + private Date createTime; + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigUpdateReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigUpdateReqVO.java new file mode 100755 index 000000000..134f3e9df --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigUpdateReqVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.infra.controller.admin.db.vo; + +import lombok.*; +import java.util.*; +import io.swagger.annotations.*; +import javax.validation.constraints.*; + +@ApiModel("管理后台 - 数据源配置更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class DataSourceConfigUpdateReqVO extends DataSourceConfigBaseVO { + + @ApiModelProperty(value = "主键编号", required = true, example = "1024") + @NotNull(message = "主键编号不能为空") + private Long id; + + @ApiModelProperty(value = "密码", required = true, example = "123456") + @NotNull(message = "密码不能为空") + private String password; + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/db/DataSourceConfigConvert.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/db/DataSourceConfigConvert.java new file mode 100755 index 000000000..d81d85cee --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/db/DataSourceConfigConvert.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.infra.convert.db; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; +import cn.iocoder.yudao.module.infra.controller.admin.db.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; + +/** + * 数据源配置 Convert + * + * @author 芋道源码 + */ +@Mapper +public interface DataSourceConfigConvert { + + DataSourceConfigConvert INSTANCE = Mappers.getMapper(DataSourceConfigConvert.class); + + DataSourceConfigDO convert(DataSourceConfigCreateReqVO bean); + + DataSourceConfigDO convert(DataSourceConfigUpdateReqVO bean); + + DataSourceConfigRespVO convert(DataSourceConfigDO bean); + + List convertList(List list); + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DataSourceConfigDO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DataSourceConfigDO.java new file mode 100644 index 000000000..6508d1d18 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DataSourceConfigDO.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.db; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * 数据源配置 + * + * @author 芋道源码 + */ +@TableName("infra_data_source_config") +@Data +public class DataSourceConfigDO extends BaseDO { + + /** + * 主键编号 + */ + private Long id; + /** + * 连接名 + */ + private String name; + + /** + * 数据源连接 + */ + private String url; + /** + * 用户名 + */ + private String username; + /** + * 密码 + */ + private String password; + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DataSourceConfigMapper.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DataSourceConfigMapper.java new file mode 100755 index 000000000..5ad8be428 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DataSourceConfigMapper.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.db; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 数据源配置 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface DataSourceConfigMapper extends BaseMapperX { +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigService.java new file mode 100755 index 000000000..b5e9e21ee --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigService.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.infra.service.db; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; +import org.w3c.dom.stylesheets.LinkStyle; + +import javax.validation.Valid; +import java.util.List; + +/** + * 数据源配置 Service 接口 + * + * @author 芋道源码 + */ +public interface DataSourceConfigService { + + /** + * 创建数据源配置 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createDataSourceConfig(@Valid DataSourceConfigCreateReqVO createReqVO); + + /** + * 更新数据源配置 + * + * @param updateReqVO 更新信息 + */ + void updateDataSourceConfig(@Valid DataSourceConfigUpdateReqVO updateReqVO); + + /** + * 删除数据源配置 + * + * @param id 编号 + */ + void deleteDataSourceConfig(Long id); + + /** + * 获得数据源配置 + * + * @param id 编号 + * @return 数据源配置 + */ + DataSourceConfigDO getDataSourceConfig(Long id); + + /** + * 获得数据源配置列表 + * + * @return 数据源配置列表 + */ + List getDataSourceConfigList(); + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImpl.java new file mode 100755 index 000000000..e2f1a6559 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImpl.java @@ -0,0 +1,97 @@ +package cn.iocoder.yudao.module.infra.service.db; + +import cn.hutool.db.DbUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.util.DatabaseUtils; +import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO; +import cn.iocoder.yudao.module.infra.convert.db.DataSourceConfigConvert; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; +import cn.iocoder.yudao.module.infra.dal.mysql.db.DataSourceConfigMapper; +import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils; +import org.jasypt.encryption.StringEncryptor; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; + +import java.sql.Connection; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.DATA_SOURCE_CONFIG_NOT_EXISTS; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.DATA_SOURCE_CONFIG_NOT_OK; + +/** + * 数据源配置 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class DataSourceConfigServiceImpl implements DataSourceConfigService { + + @Resource + private DataSourceConfigMapper dataSourceConfigMapper; + + @Resource + private StringEncryptor stringEncryptor; + + @Override + public Long createDataSourceConfig(DataSourceConfigCreateReqVO createReqVO) { + DataSourceConfigDO dataSourceConfig = DataSourceConfigConvert.INSTANCE.convert(createReqVO); + checkConnectionOK(dataSourceConfig); + + // 插入 + dataSourceConfig.setPassword(stringEncryptor.encrypt(createReqVO.getPassword())); + dataSourceConfigMapper.insert(dataSourceConfig); + // 返回 + return dataSourceConfig.getId(); + } + + @Override + public void updateDataSourceConfig(DataSourceConfigUpdateReqVO updateReqVO) { + // 校验存在 + validateDataSourceConfigExists(updateReqVO.getId()); + DataSourceConfigDO updateObj = DataSourceConfigConvert.INSTANCE.convert(updateReqVO); + checkConnectionOK(updateObj); + + // 更新 + updateObj.setPassword(stringEncryptor.encrypt(updateObj.getPassword())); + dataSourceConfigMapper.updateById(updateObj); + } + + @Override + public void deleteDataSourceConfig(Long id) { + // 校验存在 + validateDataSourceConfigExists(id); + // 删除 + dataSourceConfigMapper.deleteById(id); + } + + private void validateDataSourceConfigExists(Long id) { + if (dataSourceConfigMapper.selectById(id) == null) { + throw exception(DATA_SOURCE_CONFIG_NOT_EXISTS); + } + } + + @Override + public DataSourceConfigDO getDataSourceConfig(Long id) { + DataSourceConfigDO dataSourceConfig = dataSourceConfigMapper.selectById(id); + dataSourceConfig.setPassword(stringEncryptor.decrypt(dataSourceConfig.getPassword())); + return dataSourceConfig; + } + + @Override + public List getDataSourceConfigList() { + return dataSourceConfigMapper.selectList(); + } + + private void checkConnectionOK(DataSourceConfigDO config) { + boolean success = DatabaseUtils.isConnectionOK(config.getUrl(), config.getUsername(), config.getPassword()); + if (!success) { + throw exception(DATA_SOURCE_CONFIG_NOT_OK); + } + } + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImplTest.java b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImplTest.java new file mode 100755 index 000000000..5c51b198e --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImplTest.java @@ -0,0 +1,119 @@ +package cn.iocoder.yudao.module.infra.service.db; + +import cn.iocoder.yudao.framework.mybatis.core.util.DatabaseUtils; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; +import cn.iocoder.yudao.module.infra.dal.mysql.db.DataSourceConfigMapper; +import org.jasypt.encryption.StringEncryptor; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; + +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.DATA_SOURCE_CONFIG_NOT_EXISTS; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * {@link DataSourceConfigServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(DataSourceConfigServiceImpl.class) +public class DataSourceConfigServiceImplTest extends BaseDbUnitTest { + + @Resource + private DataSourceConfigServiceImpl dataSourceConfigService; + + @Resource + private DataSourceConfigMapper dataSourceConfigMapper; + + @MockBean + private StringEncryptor stringEncryptor; + + @Test + public void testCreateDataSourceConfig_success() { + try (MockedStatic databaseUtilsMock = mockStatic(DatabaseUtils.class)) { + // 准备参数 + DataSourceConfigCreateReqVO reqVO = randomPojo(DataSourceConfigCreateReqVO.class); + // mock 方法 + when(stringEncryptor.encrypt(eq(reqVO.getPassword()))).thenReturn("123456"); + databaseUtilsMock.when(() -> DatabaseUtils.isConnectionOK(eq(reqVO.getUrl()), + eq(reqVO.getUsername()), eq(reqVO.getPassword()))).thenReturn(true); + + // 调用 + Long dataSourceConfigId = dataSourceConfigService.createDataSourceConfig(reqVO); + // 断言 + assertNotNull(dataSourceConfigId); + // 校验记录的属性是否正确 + DataSourceConfigDO dataSourceConfig = dataSourceConfigMapper.selectById(dataSourceConfigId); + assertPojoEquals(reqVO, dataSourceConfig, "password"); + assertEquals("123456", dataSourceConfig.getPassword()); + } + } + + @Test + public void testUpdateDataSourceConfig_success() { + try (MockedStatic databaseUtilsMock = mockStatic(DatabaseUtils.class)) { + // mock 数据 + DataSourceConfigDO dbDataSourceConfig = randomPojo(DataSourceConfigDO.class); + dataSourceConfigMapper.insert(dbDataSourceConfig);// @Sql: 先插入出一条存在的数据 + // 准备参数 + DataSourceConfigUpdateReqVO reqVO = randomPojo(DataSourceConfigUpdateReqVO.class, o -> { + o.setId(dbDataSourceConfig.getId()); // 设置更新的 ID + }); + // mock 方法 + when(stringEncryptor.encrypt(eq(reqVO.getPassword()))).thenReturn("123456"); + databaseUtilsMock.when(() -> DatabaseUtils.isConnectionOK(eq(reqVO.getUrl()), + eq(reqVO.getUsername()), eq(reqVO.getPassword()))).thenReturn(true); + + // 调用 + dataSourceConfigService.updateDataSourceConfig(reqVO); + // 校验是否更新正确 + DataSourceConfigDO dataSourceConfig = dataSourceConfigMapper.selectById(reqVO.getId()); // 获取最新的 + assertPojoEquals(reqVO, dataSourceConfig, "password"); + assertEquals("123456", dataSourceConfig.getPassword()); + } + } + + @Test + public void testUpdateDataSourceConfig_notExists() { + // 准备参数 + DataSourceConfigUpdateReqVO reqVO = randomPojo(DataSourceConfigUpdateReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> dataSourceConfigService.updateDataSourceConfig(reqVO), DATA_SOURCE_CONFIG_NOT_EXISTS); + } + + @Test + public void testDeleteDataSourceConfig_success() { + // mock 数据 + DataSourceConfigDO dbDataSourceConfig = randomPojo(DataSourceConfigDO.class); + dataSourceConfigMapper.insert(dbDataSourceConfig);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbDataSourceConfig.getId(); + + // 调用 + dataSourceConfigService.deleteDataSourceConfig(id); + // 校验数据不存在了 + assertNull(dataSourceConfigMapper.selectById(id)); + } + + @Test + public void testDeleteDataSourceConfig_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> dataSourceConfigService.deleteDataSourceConfig(id), DATA_SOURCE_CONFIG_NOT_EXISTS); + } + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/clean.sql b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/clean.sql index cc8316837..eb05d3d5a 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/clean.sql +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/clean.sql @@ -9,3 +9,4 @@ DELETE FROM "infra_file"; DELETE FROM "infra_api_error_log"; DELETE FROM "infra_test_demo"; DELETE FROM "infra_file_config"; +DELETE FROM "infra_data_source_config"; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/create_tables.sql b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/create_tables.sql index 3c86102e6..53d8594fe 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/create_tables.sql +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/create_tables.sql @@ -168,3 +168,17 @@ CREATE TABLE IF NOT EXISTS "infra_test_demo" ( "deleted" bit NOT NULL DEFAULT FALSE, PRIMARY KEY ("id") ) COMMENT '字典类型表'; + +CREATE TABLE IF NOT EXISTS "infra_data_source_config" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar(100) NOT NULL, + "url" varchar(1024) NOT NULL, + "username" varchar(255) NOT NULL, + "password" varchar(255) NOT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") +) COMMENT '数据源配置表'; diff --git a/yudao-module-member/yudao-module-member-biz/pom.xml b/yudao-module-member/yudao-module-member-biz/pom.xml index f1b48a819..11780b8a0 100644 --- a/yudao-module-member/yudao-module-member-biz/pom.xml +++ b/yudao-module-member/yudao-module-member-biz/pom.xml @@ -77,8 +77,8 @@ yudao-spring-boot-starter-test test - + diff --git a/yudao-server/src/main/resources/application-dev.yaml b/yudao-server/src/main/resources/application-dev.yaml index 256c5beb8..0c11d2f1b 100644 --- a/yudao-server/src/main/resources/application-dev.yaml +++ b/yudao-server/src/main/resources/application-dev.yaml @@ -61,6 +61,10 @@ spring: port: 6379 # 端口 database: 1 # 数据库索引 +jasypt: + encryptor: + password: yuanma # 加解密的秘钥 + --- #################### 定时任务相关配置 #################### # Quartz 配置项,对应 QuartzProperties 配置类 diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 0d5f777d0..d8ce9deee 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -61,6 +61,10 @@ spring: port: 6379 # 端口 database: 0 # 数据库索引 +jasypt: + encryptor: + password: yuanma # 加解密的秘钥 + --- #################### 定时任务相关配置 #################### # Quartz 配置项,对应 QuartzProperties 配置类 diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 76d5e0454..247af4d03 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -123,6 +123,7 @@ yudao: - infra_job - infra_job_log - infra_job_log + - infra_data_source_config sms-code: # 短信验证码相关的配置项 expire-times: 10m send-frequency: 1m diff --git a/yudao-ui-admin/src/api/infra/dataSourceConfig.js b/yudao-ui-admin/src/api/infra/dataSourceConfig.js new file mode 100755 index 000000000..2d96b49cc --- /dev/null +++ b/yudao-ui-admin/src/api/infra/dataSourceConfig.js @@ -0,0 +1,43 @@ +import request from '@/utils/request' + +// 创建数据源配置 +export function createDataSourceConfig(data) { + return request({ + url: '/infra/data-source-config/create', + method: 'post', + data: data + }) +} + +// 更新数据源配置 +export function updateDataSourceConfig(data) { + return request({ + url: '/infra/data-source-config/update', + method: 'put', + data: data + }) +} + +// 删除数据源配置 +export function deleteDataSourceConfig(id) { + return request({ + url: '/infra/data-source-config/delete?id=' + id, + method: 'delete' + }) +} + +// 获得数据源配置 +export function getDataSourceConfig(id) { + return request({ + url: '/infra/data-source-config/get?id=' + id, + method: 'get' + }) +} + +// 获得数据源配置列表 +export function getDataSourceConfigList() { + return request({ + url: '/infra/data-source-config/list', + method: 'get', + }) +} diff --git a/yudao-ui-admin/src/views/infra/dataSourceConfig/index.vue b/yudao-ui-admin/src/views/infra/dataSourceConfig/index.vue new file mode 100755 index 000000000..ddd2800a2 --- /dev/null +++ b/yudao-ui-admin/src/views/infra/dataSourceConfig/index.vue @@ -0,0 +1,166 @@ + + + + + + 新增 + + + + + + + + + + + + {{ parseTime(scope.row.createTime) }} + + + + + 修改 + 删除 + + + + + + + + + + + + + + + + + + + + + + + + + +