mirror of
https://gitee.com/hhyykk/ipms-sjy.git
synced 2025-08-01 20:04:06 +08:00
Merge branch 'master' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/1.8.0-uniapp
Conflicts: yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/UserController.java yudao-ui-admin/src/components/ImageUpload/index.vue
This commit is contained in:
@@ -1,15 +1,12 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.file;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileRespVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.UploadRespVO;
|
||||
import cn.iocoder.yudao.module.infra.convert.file.FileConvert;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO;
|
||||
import cn.iocoder.yudao.module.infra.service.file.FileService;
|
||||
@@ -46,20 +43,10 @@ public class FileController {
|
||||
@ApiImplicitParam(name = "file", value = "文件附件", required = true, dataTypeClass = MultipartFile.class),
|
||||
@ApiImplicitParam(name = "path", value = "文件路径", example = "yudaoyuanma.png", dataTypeClass = String.class)
|
||||
})
|
||||
public CommonResult<UploadRespVO> uploadFile(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "path", required = false) String path)
|
||||
throws Exception {
|
||||
// 如果路径没传, 系统生成随机路径
|
||||
if (StrUtil.isBlank(path)) {
|
||||
// TODO 生成带日期的路径, 目前 #getFileContent 不支持
|
||||
path = IdUtil.fastSimpleUUID() + StrUtil.DOT + FileUtil.extName(file.getOriginalFilename());
|
||||
}
|
||||
String fileUrl = fileService.createFile(path, IoUtil.readBytes(file.getInputStream()));
|
||||
// 返回结果
|
||||
UploadRespVO uploadRespVO = new UploadRespVO();
|
||||
uploadRespVO.setFileName(file.getOriginalFilename());
|
||||
uploadRespVO.setFileUrl(fileUrl);
|
||||
return success(uploadRespVO);
|
||||
@OperateLog(logArgs = false) // 上传文件,没有记录操作日志的必要
|
||||
public CommonResult<String> uploadFile(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "path", required = false) String path) throws Exception {
|
||||
return success(fileService.createFile(path, IoUtil.readBytes(file.getInputStream())));
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
|
@@ -1,7 +1,9 @@
|
||||
package cn.iocoder.yudao.module.infra.dal.dataobject.db;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.type.EncryptTypeHandler;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -10,7 +12,7 @@ import lombok.Data;
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("infra_data_source_config")
|
||||
@TableName(value = "infra_data_source_config", autoResultMap = true)
|
||||
@KeySequence("infra_data_source_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
public class DataSourceConfigDO extends BaseDO {
|
||||
@@ -40,6 +42,7 @@ public class DataSourceConfigDO extends BaseDO {
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
@TableField(typeHandler = EncryptTypeHandler.class)
|
||||
private String password;
|
||||
|
||||
}
|
||||
|
@@ -206,7 +206,7 @@ public class CodegenServiceImpl implements CodegenService {
|
||||
public Map<String, String> generationCodes(Long tableId) {
|
||||
// 校验是否已经存在
|
||||
CodegenTableDO table = codegenTableMapper.selectById(tableId);
|
||||
if (codegenTableMapper.selectById(tableId) == null) {
|
||||
if (table == null) {
|
||||
throw exception(CODEGEN_TABLE_NOT_EXISTS);
|
||||
}
|
||||
List<CodegenColumnDO> columns = codegenColumnMapper.selectListByTableId(tableId);
|
||||
|
@@ -8,7 +8,6 @@ import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.mysql.db.DataSourceConfigMapper;
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
|
||||
import org.jasypt.encryption.StringEncryptor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
@@ -32,9 +31,6 @@ public class DataSourceConfigServiceImpl implements DataSourceConfigService {
|
||||
@Resource
|
||||
private DataSourceConfigMapper dataSourceConfigMapper;
|
||||
|
||||
@Resource
|
||||
private StringEncryptor stringEncryptor;
|
||||
|
||||
@Resource
|
||||
private DynamicDataSourceProperties dynamicDataSourceProperties;
|
||||
|
||||
@@ -44,7 +40,6 @@ public class DataSourceConfigServiceImpl implements DataSourceConfigService {
|
||||
checkConnectionOK(dataSourceConfig);
|
||||
|
||||
// 插入
|
||||
dataSourceConfig.setPassword(stringEncryptor.encrypt(createReqVO.getPassword()));
|
||||
dataSourceConfigMapper.insert(dataSourceConfig);
|
||||
// 返回
|
||||
return dataSourceConfig.getId();
|
||||
@@ -58,7 +53,6 @@ public class DataSourceConfigServiceImpl implements DataSourceConfigService {
|
||||
checkConnectionOK(updateObj);
|
||||
|
||||
// 更新
|
||||
updateObj.setPassword(stringEncryptor.encrypt(updateObj.getPassword()));
|
||||
dataSourceConfigMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@@ -83,12 +77,7 @@ public class DataSourceConfigServiceImpl implements DataSourceConfigService {
|
||||
return buildMasterDataSourceConfig();
|
||||
}
|
||||
// 从 DB 中读取
|
||||
DataSourceConfigDO dataSourceConfig = dataSourceConfigMapper.selectById(id);
|
||||
try {
|
||||
dataSourceConfig.setPassword(stringEncryptor.decrypt(dataSourceConfig.getPassword()));
|
||||
} catch (Exception ignore) { // 解码失败,则不解码
|
||||
}
|
||||
return dataSourceConfig;
|
||||
return dataSourceConfigMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.infra.service.file;
|
||||
|
||||
import cn.hutool.core.io.FileTypeUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.digest.DigestUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.file.core.client.FileClient;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO;
|
||||
@@ -36,6 +38,12 @@ public class FileServiceImpl implements FileService {
|
||||
|
||||
@Override
|
||||
public String createFile(String path, byte[] content) throws Exception {
|
||||
// 计算默认的 path 名
|
||||
String type = FileTypeUtil.getType(new ByteArrayInputStream(content), path);
|
||||
if (StrUtil.isEmpty(path)) {
|
||||
path = DigestUtil.md5Hex(content) + '.' + type;
|
||||
}
|
||||
|
||||
// 上传到文件存储器
|
||||
FileClient client = fileConfigService.getMasterFileClient();
|
||||
Assert.notNull(client, "客户端(master) 不能为空");
|
||||
@@ -46,7 +54,7 @@ public class FileServiceImpl implements FileService {
|
||||
file.setConfigId(client.getId());
|
||||
file.setPath(path);
|
||||
file.setUrl(url);
|
||||
file.setType(FileTypeUtil.getType(new ByteArrayInputStream(content)));
|
||||
file.setType(type);
|
||||
file.setSize(content.length);
|
||||
fileMapper.insert(file);
|
||||
return url;
|
||||
|
@@ -30,7 +30,7 @@ public class ${table.className}DO extends BaseDO {
|
||||
#end
|
||||
*/
|
||||
#if (${column.primaryKey})##处理主键
|
||||
@TableId#if (${column.javaType} == 'String')type = IdType.INPUT)#end
|
||||
@TableId#if (${column.javaType} == 'String')(type = IdType.INPUT)#end
|
||||
#end
|
||||
private ${column.javaType} ${column.javaField};
|
||||
#end
|
||||
|
@@ -9,6 +9,7 @@ VALUES (
|
||||
);
|
||||
|
||||
-- 按钮父菜单ID
|
||||
-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码
|
||||
SELECT @parentId := LAST_INSERT_ID();
|
||||
|
||||
-- 按钮 SQL
|
||||
|
@@ -27,8 +27,8 @@ public class DefaultDatabaseQueryTest {
|
||||
if (StrUtil.startWithAny(tableInfo.getName().toLowerCase(), "act_", "flw_", "qrtz_")) {
|
||||
continue;
|
||||
}
|
||||
// System.out.println(String.format("CREATE SEQUENCE %s_seq MINVALUE 0;", tableInfo.getName()));
|
||||
System.out.println(String.format("DELETE FROM %s WHERE deleted = '1';", tableInfo.getName()));
|
||||
System.out.println(String.format("CREATE SEQUENCE %s_seq MINVALUE 1;", tableInfo.getName()));
|
||||
// System.out.println(String.format("DELETE FROM %s WHERE deleted = '1';", tableInfo.getName()));
|
||||
}
|
||||
System.out.println(tableInfos.size());
|
||||
System.out.println(System.currentTimeMillis() - time);
|
||||
|
@@ -1,5 +1,7 @@
|
||||
package cn.iocoder.yudao.module.infra.service.db;
|
||||
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.type.EncryptTypeHandler;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO;
|
||||
@@ -8,8 +10,10 @@ import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.mysql.db.DataSourceConfigMapper;
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
|
||||
import org.jasypt.encryption.StringEncryptor;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
@@ -21,7 +25,10 @@ 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.*;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* {@link DataSourceConfigServiceImpl} 的单元测试类
|
||||
@@ -43,13 +50,20 @@ public class DataSourceConfigServiceImplTest extends BaseDbUnitTest {
|
||||
@MockBean
|
||||
private DynamicDataSourceProperties dynamicDataSourceProperties;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
// mock 一个空实现的 StringEncryptor,避免 EncryptTypeHandler 报错
|
||||
ReflectUtil.setFieldValue(EncryptTypeHandler.class, "encryptor", stringEncryptor);
|
||||
when(stringEncryptor.encrypt(anyString())).then((Answer<String>) invocation -> invocation.getArgument(0));
|
||||
when(stringEncryptor.decrypt(anyString())).then((Answer<String>) invocation -> invocation.getArgument(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateDataSourceConfig_success() {
|
||||
try (MockedStatic<JdbcUtils> databaseUtilsMock = mockStatic(JdbcUtils.class)) {
|
||||
// 准备参数
|
||||
DataSourceConfigCreateReqVO reqVO = randomPojo(DataSourceConfigCreateReqVO.class);
|
||||
// mock 方法
|
||||
when(stringEncryptor.encrypt(eq(reqVO.getPassword()))).thenReturn("123456");
|
||||
databaseUtilsMock.when(() -> JdbcUtils.isConnectionOK(eq(reqVO.getUrl()),
|
||||
eq(reqVO.getUsername()), eq(reqVO.getPassword()))).thenReturn(true);
|
||||
|
||||
@@ -59,8 +73,7 @@ public class DataSourceConfigServiceImplTest extends BaseDbUnitTest {
|
||||
assertNotNull(dataSourceConfigId);
|
||||
// 校验记录的属性是否正确
|
||||
DataSourceConfigDO dataSourceConfig = dataSourceConfigMapper.selectById(dataSourceConfigId);
|
||||
assertPojoEquals(reqVO, dataSourceConfig, "password");
|
||||
assertEquals("123456", dataSourceConfig.getPassword());
|
||||
assertPojoEquals(reqVO, dataSourceConfig);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +88,7 @@ public class DataSourceConfigServiceImplTest extends BaseDbUnitTest {
|
||||
o.setId(dbDataSourceConfig.getId()); // 设置更新的 ID
|
||||
});
|
||||
// mock 方法
|
||||
when(stringEncryptor.encrypt(eq(reqVO.getPassword()))).thenReturn("123456");
|
||||
// when(stringEncryptor.encrypt(eq(reqVO.getPassword()))).thenReturn("123456");
|
||||
databaseUtilsMock.when(() -> JdbcUtils.isConnectionOK(eq(reqVO.getUrl()),
|
||||
eq(reqVO.getUsername()), eq(reqVO.getPassword()))).thenReturn(true);
|
||||
|
||||
@@ -83,8 +96,7 @@ public class DataSourceConfigServiceImplTest extends BaseDbUnitTest {
|
||||
dataSourceConfigService.updateDataSourceConfig(reqVO);
|
||||
// 校验是否更新正确
|
||||
DataSourceConfigDO dataSourceConfig = dataSourceConfigMapper.selectById(reqVO.getId()); // 获取最新的
|
||||
assertPojoEquals(reqVO, dataSourceConfig, "password");
|
||||
assertEquals("123456", dataSourceConfig.getPassword());
|
||||
assertPojoEquals(reqVO, dataSourceConfig);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,4 +132,16 @@ public class DataSourceConfigServiceImplTest extends BaseDbUnitTest {
|
||||
assertServiceException(() -> dataSourceConfigService.deleteDataSourceConfig(id), DATA_SOURCE_CONFIG_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test // 测试使用 password 查询,可以查询到数据
|
||||
public void testSelectPassword() {
|
||||
// mock 数据
|
||||
DataSourceConfigDO dbDataSourceConfig = randomPojo(DataSourceConfigDO.class);
|
||||
dataSourceConfigMapper.insert(dbDataSourceConfig);// @Sql: 先插入出一条存在的数据
|
||||
|
||||
// 调用
|
||||
DataSourceConfigDO result = dataSourceConfigMapper.selectOne(DataSourceConfigDO::getPassword,
|
||||
EncryptTypeHandler.encrypt(dbDataSourceConfig.getPassword()));
|
||||
System.out.println(result);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,12 +1,12 @@
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "infra_config" (
|
||||
"id" bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"group" varchar(50) NOT NULL,
|
||||
"category" varchar(50) NOT NULL,
|
||||
"type" tinyint NOT NULL,
|
||||
"name" varchar(100) NOT NULL DEFAULT '',
|
||||
"key" varchar(100) NOT NULL DEFAULT '',
|
||||
"config_key" varchar(100) NOT NULL DEFAULT '',
|
||||
"value" varchar(500) NOT NULL DEFAULT '',
|
||||
"sensitive" bit NOT NULL,
|
||||
"visible" bit NOT NULL,
|
||||
"remark" varchar(500) DEFAULT NULL,
|
||||
"creator" varchar(64) DEFAULT '',
|
||||
"create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
Reference in New Issue
Block a user