Complete the datasource code

This commit is contained in:
JiaJu Zhuang
2023-08-05 21:22:28 +08:00
parent ab4801d97b
commit c09ee3156e
37 changed files with 176 additions and 127 deletions

View File

@ -12,4 +12,9 @@ api.tag=#version
constant.field.ignore=groovy:it.name()=="serialVersionUID" constant.field.ignore=groovy:it.name()=="serialVersionUID"
# sprnSupport for Jackson annotations # sprnSupport for Jackson annotations
json.rule.field.ignore=@com.fasterxml.jackson.annotation.JsonIgnore#value json.rule.field.ignore=@com.fasterxml.jackson.annotation.JsonIgnore#value
field.demo=#demo
field.default.value=#default
#apifox mock
field.mock=#mock

View File

@ -12,4 +12,4 @@ api.tag=#version
constant.field.ignore=groovy:it.name()=="serialVersionUID" constant.field.ignore=groovy:it.name()=="serialVersionUID"
# sprnSupport for Jackson annotations # sprnSupport for Jackson annotations
json.rule.field.ignore=@com.fasterxml.jackson.annotation.JsonIgnore#value json.rule.field.ignore=@com.fasterxml.jackson.annotation.JsonIgnore#value

View File

@ -13,25 +13,29 @@ public enum RoleCodeEnum implements BaseEnum<String> {
/** /**
* DESKTOP * DESKTOP
*/ */
DESKTOP("DESKTOP", 1L), DESKTOP("DESKTOP", 1L, "_desktop_default_user_name", "_desktop_default_user_name"),
/** /**
* ADMIN * ADMIN
*/ */
ADMIN("ADMIN", 2L), ADMIN("ADMIN", 2L, "chat2db", "chat2db"),
/** /**
* USER * USER
*/ */
USER("USER", null), USER("USER", null, null, null),
; ;
final String description; final String description;
final Long defaultUserId; final Long defaultUserId;
final String userName;
final String password;
RoleCodeEnum(String description, Long defaultUserId) { RoleCodeEnum(String description, Long defaultUserId, String userName, String password) {
this.description = description; this.description = description;
this.defaultUserId = defaultUserId; this.defaultUserId = defaultUserId;
this.userName = userName;
this.password = password;
} }
@Override @Override

View File

@ -33,7 +33,7 @@ public class MemoryCacheManage {
.createCache(CACHE, .createCache(CACHE,
CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, byte[].class, CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, byte[].class,
ResourcePoolsBuilder.newResourcePoolsBuilder() ResourcePoolsBuilder.newResourcePoolsBuilder()
.offheap(10, MemoryUnit.MB)) .offheap(5, MemoryUnit.MB))
.withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMinutes(10)))); .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMinutes(10))));
} }

View File

@ -14,7 +14,7 @@ import lombok.Setter;
* </p> * </p>
* *
* @author chat2db * @author chat2db
* @since 2023-07-30 * @since 2023-08-05
*/ */
@Getter @Getter
@Setter @Setter

View File

@ -1,6 +1,7 @@
package ai.chat2db.server.domain.repository.mapper; package ai.chat2db.server.domain.repository.mapper;
import ai.chat2db.server.domain.repository.entity.DataSourceDO; import ai.chat2db.server.domain.repository.entity.DataSourceDO;
import com.baomidou.mybatisplus.core.mapper.Mapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
@ -9,8 +10,9 @@ import org.apache.ibatis.annotations.Param;
* *
* @author Jiaju Zhuang * @author Jiaju Zhuang
*/ */
public interface DataSourceCustomMapper { public interface DataSourceCustomMapper extends Mapper<DataSourceDO> {
IPage<DataSourceDO> selectPageWithPermission(IPage<DataSourceDO> page, @Param("admin") Boolean admin,
@Param("userId") Long userId,
@Param("searchKey") String searchKey);
IPage<DataSourceDO> selectPageWithPermission(IPage<DataSourceDO> page, @Param("admin") Boolean admin, @Param("userId") Long userId,
@Param("searchKey") String searchKey);
} }

View File

@ -1,32 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="ai.chat2db.server.domain.repository.mapper.DataSourceCustomMapper">
<select id="selectPageWithPermission" resultType="ai.chat2db.server.domain.repository.entity.DataSourceDO">
select ds.*
from DATA_SOURCE ds
<where>
<if test="admin != true">
<choose>
<when test="userId == 1">
ds.USER_ID = #{userId}
</when>
<otherwise>
(ds.USER_ID = #{userId}
or exists(select 1 from DATA_SOURCE_ACCESS dsa where dsa.ACCESS_OBJECT_TYPE = 'USER' and
dsa.ACCESS_OBJECT_ID = #{userId})
or exists(select 1
from DATA_SOURCE_ACCESS dsa
LEFT JOIN TEAM_USER tu on tu.ID = dsa.ACCESS_OBJECT_ID and dsa.ACCESS_OBJECT_TYPE = 'TEAM'
where tu.USER_ID = #{userId})
)
</otherwise>
</choose>
</if>
<if test="searchKey != '' and searchKey != null ">
and (ds.alias like concat('%',#{searchKey},'%') or ds.url like concat('%',#{searchKey},'%'))
</if>
</where>
</select>
</mapper>

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="ai.chat2db.server.domain.repository.mapper.DataSourceCustomMapper">
<select id="selectPageWithPermission" resultType="ai.chat2db.server.domain.repository.entity.DataSourceDO">
select ds.*
from DATA_SOURCE ds
<where>
<choose>
<when test="admin == true">
and ds.USER_ID != 1
</when>
<otherwise>
<choose>
<when test="userId == 1">
and ds.USER_ID = #{userId}
</when>
<otherwise>
and (ds.USER_ID = #{userId}
or exists(select 1 from DATA_SOURCE_ACCESS dsa where dsa.ACCESS_OBJECT_TYPE = 'USER' and
dsa.ACCESS_OBJECT_ID = #{userId})
or exists(select 1
from DATA_SOURCE_ACCESS dsa
LEFT JOIN TEAM_USER tu on tu.ID = dsa.ACCESS_OBJECT_ID and dsa.ACCESS_OBJECT_TYPE = 'TEAM'
where tu.USER_ID = #{userId})
)
</otherwise>
</choose>
</otherwise>
</choose>
<if test="searchKey != '' and searchKey != null ">
and (ds.alias like concat('%',#{searchKey},'%') or ds.url like concat('%',#{searchKey},'%'))
</if>
</where>
</select>
</mapper>

View File

@ -28,7 +28,10 @@
<groupId>ai.chat2db</groupId> <groupId>ai.chat2db</groupId>
<artifactId>chat2db-server-web-api</artifactId> <artifactId>chat2db-server-web-api</artifactId>
</dependency> </dependency>
<dependency>
<groupId>ai.chat2db</groupId>
<artifactId>chat2db-server-admin-api</artifactId>
</dependency>
<!-- 需要加载的服务 --> <!-- 需要加载的服务 -->
<dependency> <dependency>
<groupId>ai.chat2db</groupId> <groupId>ai.chat2db</groupId>

View File

@ -47,7 +47,7 @@ public class Application {
ModeEnum mode = EasyEnumUtils.getEnum(ModeEnum.class, System.getProperty("chat2db.mode")); ModeEnum mode = EasyEnumUtils.getEnum(ModeEnum.class, System.getProperty("chat2db.mode"));
if (mode == ModeEnum.DESKTOP) { if (mode == ModeEnum.DESKTOP) {
// In this mode, no user login is required, so only local access is available // In this mode, no user login is required, so only local access is available
args = ArrayUtils.add(args, "--server.address = 0.0.0.0"); args = ArrayUtils.add(args, "--server.address=0.0.0.0");
} }
SpringApplication.run(Application.class, args); SpringApplication.run(Application.class, args);
} }

View File

@ -77,8 +77,9 @@ public class Chat2dbWebMvcConfigurer implements WebMvcConfigurer {
} else { } else {
return true; return true;
} }
} else {
userId = Long.parseLong(userIdString);
} }
userId = Long.parseLong(userIdString);
Long finalUserId = userId; Long finalUserId = userId;
LoginUser loginUser = MemoryCacheManage.computeIfAbsent(CacheKey.getLoginUserKey(userId), () -> { LoginUser loginUser = MemoryCacheManage.computeIfAbsent(CacheKey.getLoginUserKey(userId), () -> {
User user = userService.query(finalUserId).getData(); User user = userService.query(finalUserId).getData();

View File

@ -1,5 +1,6 @@
package ai.chat2db.server.start.controller.oauth; package ai.chat2db.server.start.controller.oauth;
import ai.chat2db.server.domain.api.enums.RoleCodeEnum;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import ai.chat2db.server.domain.api.model.User; import ai.chat2db.server.domain.api.model.User;
@ -47,14 +48,26 @@ public class OauthController {
// 查询用户 // 查询用户
User user = userService.query(request.getUserName()).getData(); User user = userService.query(request.getUserName()).getData();
if (user == null) { if (user == null) {
throw new BusinessException("当前用户不存在。"); throw new BusinessException("oauth.userNameNotExits");
} }
if (RoleCodeEnum.DESKTOP.getDefaultUserId().equals(user.getId())) {
throw new BusinessException("oauth.IllegalUserName");
}
// Successfully logged in without modifying the administrator password
if (RoleCodeEnum.ADMIN.getDefaultUserId().equals(user.getId()) && RoleCodeEnum.ADMIN.getPassword().equals(
user.getPassword())) {
return DataResult.of(doLogin(user));
}
if (!DigestUtil.bcryptCheck(request.getPassword(), user.getPassword())) { if (!DigestUtil.bcryptCheck(request.getPassword(), user.getPassword())) {
throw new BusinessException("您输入的密码有误。"); throw new BusinessException("oauth.passwordIncorrect");
} }
return DataResult.of(doLogin(user));
}
private Object doLogin(User user) {
StpUtil.login(user.getId()); StpUtil.login(user.getId());
Object token = SaHolder.getStorage().get(SaTokenConsts.JUST_CREATED_NOT_PREFIX); return SaHolder.getStorage().get(SaTokenConsts.JUST_CREATED_NOT_PREFIX);
return DataResult.of(token);
} }
/** /**

View File

@ -32,7 +32,7 @@ spring:
multipart: multipart:
max-file-size: -1 max-file-size: -1
max-request-size: -1 max-request-size: -1
chat2db: chat2db:
version: 1.0.0 version: 1.0.0
@ -41,6 +41,12 @@ logging:
level: level:
org: org:
flywaydb: debug flywaydb: debug
ai:
chat2db:
server:
domain:
repository:
mapper: debug
# 登录功能 # 登录功能
sa-token: sa-token:
# token名称 (同时也是cookie名称) # token名称 (同时也是cookie名称)

View File

@ -38,8 +38,11 @@ ALTER TABLE `dbhub_user`
update dbhub_user update dbhub_user
set role_code= 'DESKTOP' set role_code= 'DESKTOP',user_name='_desktop_default_user_name',password='_desktop_default_user_name',nick_name='桌面端用户'
where id = 1; where id = 1;
INSERT INTO DBHUB_USER (USER_NAME, PASSWORD, NICK_NAME, EMAIL, ROLE_CODE) VALUES ('chat2db', 'chat2db', '管理员', null, 'ADMIN');
create UNIQUE INDEX uk_user_user_name on dbhub_user (user_name);
CREATE TABLE IF NOT EXISTS `team` CREATE TABLE IF NOT EXISTS `team`

View File

@ -8,6 +8,11 @@ common.paramDetailError=The parameter: {0} is incorrect
common.paramCheckError=The following parameters are not valid: common.paramCheckError=The following parameters are not valid:
common.maxUploadSize=The file exceeds the maximum limit common.maxUploadSize=The file exceeds the maximum limit
common.permissionDenied=Permission denied common.permissionDenied=Permission denied
oauth.userNameNotExits=The current account does not exist
oauth.IllegalUserName=The current account cannot be logged in. Please change your account
oauth.passwordIncorrect=The password you entered is incorrect
# dataSource # dataSource
dataSource.sqlAnalysisError=Invalid statements dataSource.sqlAnalysisError=Invalid statements
# connection # connection

View File

@ -8,6 +8,10 @@ common.paramCheckError=The following parameters are not valid
common.maxUploadSize=The file exceeds the maximum limit common.maxUploadSize=The file exceeds the maximum limit
common.permissionDenied=Permission denied common.permissionDenied=Permission denied
oauth.userNameNotExits=The current account does not exist
oauth.IllegalUserName=The current account cannot be logged in. Please change your account
oauth.passwordError=The password you entered is incorrect
dataSource.sqlAnalysisError=Invalid statements dataSource.sqlAnalysisError=Invalid statements
connection.error=Connection failed, please check the connection information connection.error=Connection failed, please check the connection information
connection.ssh.error=SSH connection failed, please check the connection information connection.ssh.error=SSH connection failed, please check the connection information

View File

@ -8,6 +8,10 @@ common.paramCheckError=请检查以下参数:
common.maxUploadSize=您输入的文件超过最大限制 common.maxUploadSize=您输入的文件超过最大限制
common.permissionDenied=您没有权限访问该页面 common.permissionDenied=您没有权限访问该页面
oauth.userNameNotExits=当前账号不存在
oauth.IllegalUserName=当前账号无法登录,请换一个账号
oauth.passwordIncorrect=您输入的密码有误
dataSource.sqlAnalysisError=不合法的执行语句 dataSource.sqlAnalysisError=不合法的执行语句
connection.error=数据库链接异常,请检查数据库配置 connection.error=数据库链接异常,请检查数据库配置
connection.ssh.error=SSH 链接异常请检查SSH配置 connection.ssh.error=SSH 链接异常请检查SSH配置

View File

@ -34,7 +34,7 @@ public class MybatisGeneratorTest extends BaseTest {
//doGenerator(Lists.newArrayList("operation_saved")); //doGenerator(Lists.newArrayList("operation_saved"));
//doGenerator(Lists.newArrayList("environment","data_source","team","team_dbhub_user","data_source_access", //doGenerator(Lists.newArrayList("environment","data_source","team","team_dbhub_user","data_source_access",
// "dbhub_user")); // "dbhub_user"));
doGenerator(Lists.newArrayList("team_user")); doGenerator(Lists.newArrayList("data_source"));
} }
private void doGenerator(List<String> tableList) { private void doGenerator(List<String> tableList) {
@ -45,7 +45,7 @@ public class MybatisGeneratorTest extends BaseTest {
+ "/java"; + "/java";
String xmlDir = System.getProperty("user.dir") String xmlDir = System.getProperty("user.dir")
+ "/../chat2db-server-domain/chat2db-server-domain-repository/src/main" + "/../chat2db-server-domain/chat2db-server-domain-repository/src/main"
+ "/resources/ai/chat2db/server/domain/repository"; + "/resources/mapper";
// 不要生成service controller // 不要生成service controller
Map<OutputFile, String> pathInfo = new HashMap<>(); Map<OutputFile, String> pathInfo = new HashMap<>();
@ -83,14 +83,12 @@ public class MybatisGeneratorTest extends BaseTest {
//开启实体类配置 //开启实体类配置
.entityBuilder() .entityBuilder()
.formatFileName("%sDO") .formatFileName("%sDO")
// 覆盖文件
.enableFileOverride()
//.addTableFills(new Column("gmt_create", FieldFill.INSERT)) // 表字段填充 //.addTableFills(new Column("gmt_create", FieldFill.INSERT)) // 表字段填充
//.addTableFills(new Column("update_time", FieldFill.INSERT_UPDATE)) // 表字段填充 //.addTableFills(new Column("update_time", FieldFill.INSERT_UPDATE)) // 表字段填充
//开启lombok //开启lombok
.enableLombok() .enableLombok()
.mapperBuilder() .mapperBuilder()
// 覆盖文件 //// 覆盖文件
.enableFileOverride() .enableFileOverride()
; ;

View File

@ -3,7 +3,6 @@ package ai.chat2db.server.tools.base.wrapper.request;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import ai.chat2db.server.tools.base.constant.EasyToolsConstant; import ai.chat2db.server.tools.base.constant.EasyToolsConstant;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
@ -26,11 +25,15 @@ public class PageQueryRequest implements Serializable {
private static final long serialVersionUID = EasyToolsConstant.SERIAL_VERSION_UID; private static final long serialVersionUID = EasyToolsConstant.SERIAL_VERSION_UID;
/** /**
* 页码 * 页码
*
* @mock 1
*/ */
@NotNull(message = "分页页码不能为空") @NotNull(message = "分页页码不能为空")
private Integer pageNo; private Integer pageNo;
/** /**
* 分页条数 * 分页条数
*
* @demo 10
*/ */
@NotNull(message = "分页大小不能为空") @NotNull(message = "分页大小不能为空")
@Range(min = 1, max = EasyToolsConstant.MAX_PAGE_SIZE, @Range(min = 1, max = EasyToolsConstant.MAX_PAGE_SIZE,

View File

@ -46,7 +46,7 @@ public class DataSourceAdminController {
*/ */
@GetMapping("/page") @GetMapping("/page")
public WebPageResult<DataSourcePageQueryVO> page(@Valid CommonPageQueryRequest request) { public WebPageResult<DataSourcePageQueryVO> page(@Valid CommonPageQueryRequest request) {
return dataSourceService.queryPage(dataSourceAdminConverter.request2param(request), null) return dataSourceService.queryPageWithPermission(dataSourceAdminConverter.request2param(request), null)
.mapToWeb(dataSourceAdminConverter::dto2vo); .mapToWeb(dataSourceAdminConverter::dto2vo);
} }
@ -81,6 +81,7 @@ public class DataSourceAdminController {
* *
* @param request * @param request
* @return * @return
* @version 2.1.0
*/ */
@PostMapping("/clone") @PostMapping("/clone")
public DataResult<Long> clone(@RequestBody DataSourceCloneRequest request) { public DataResult<Long> clone(@RequestBody DataSourceCloneRequest request) {
@ -92,6 +93,7 @@ public class DataSourceAdminController {
* *
* @param id * @param id
* @return * @return
* @version 2.1.0
*/ */
@DeleteMapping("/{id}") @DeleteMapping("/{id}")
public ActionResult delete(@PathVariable Long id) { public ActionResult delete(@PathVariable Long id) {

View File

@ -2,7 +2,7 @@
package ai.chat2db.server.admin.api.controller.user; package ai.chat2db.server.admin.api.controller.user;
import ai.chat2db.server.admin.api.controller.common.request.CommonPageQueryRequest; import ai.chat2db.server.admin.api.controller.common.request.CommonPageQueryRequest;
import ai.chat2db.server.admin.api.controller.user.converter.DataSourceAdminConverter; import ai.chat2db.server.admin.api.controller.user.converter.UserAdminConverter;
import ai.chat2db.server.admin.api.controller.user.request.UserCreateRequest; import ai.chat2db.server.admin.api.controller.user.request.UserCreateRequest;
import ai.chat2db.server.admin.api.controller.user.request.UserUpdateRequest; import ai.chat2db.server.admin.api.controller.user.request.UserUpdateRequest;
import ai.chat2db.server.admin.api.controller.user.vo.UserPageQueryVO; import ai.chat2db.server.admin.api.controller.user.vo.UserPageQueryVO;
@ -32,7 +32,7 @@ public class UserAdminController {
@Resource @Resource
private DataSourceService dataSourceService; private DataSourceService dataSourceService;
@Resource @Resource
private DataSourceAdminConverter dataSourceAdminConverter; private UserAdminConverter dataSourceAdminConverter;
/** /**
* Pagination query * Pagination query

View File

@ -1,66 +0,0 @@
package ai.chat2db.server.admin.api.controller.user.converter;
import ai.chat2db.server.admin.api.controller.common.request.CommonPageQueryRequest;
import ai.chat2db.server.admin.api.controller.datasource.request.DataSourceUpdateRequest;
import ai.chat2db.server.admin.api.controller.user.request.UserCreateRequest;
import ai.chat2db.server.domain.api.param.DataSourceCreateParam;
import ai.chat2db.server.domain.api.param.DataSourcePageQueryParam;
import ai.chat2db.server.domain.api.param.DataSourceUpdateParam;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
/**
* converter
*
* @author Jiaju Zhuang
*/
@Mapper(componentModel = "spring")
public abstract class DataSourceAdminConverter {
/**
* conversion
*
* @param request
* @return
*/
public abstract DataSourcePageQueryParam request2param(CommonPageQueryRequest request);
/**
* conversion
*
* @param request
* @return
*/
public abstract DataSourcePageQueryParam request2paramAccess(CommonPageQueryRequest request);
///**
// * conversion
// *
// * @param dto
// * @return
// */
//public abstract DataSourcePageQueryVO dto2vo(DataSource dto);
/**
* 参数转换
*
* @param request
* @return
*/
@Mappings({
@Mapping(source = "user", target = "userName")
})
public abstract DataSourceCreateParam createReq2param(UserCreateRequest request);
/**
* 参数转换
*
* @param request
* @return
*/
@Mappings({
@Mapping(source = "user", target = "userName")
})
public abstract DataSourceUpdateParam updateReq2param(DataSourceUpdateRequest request);
}

View File

@ -0,0 +1,58 @@
package ai.chat2db.server.admin.api.controller.user.converter;
import org.mapstruct.Mapper;
/**
* converter
*
* @author Jiaju Zhuang
*/
@Mapper(componentModel = "spring")
public abstract class UserAdminConverter {
///**
// * conversion
// *
// * @param request
// * @return
// */
//public abstract DataSourcePageQueryParam request2param(CommonPageQueryRequest request);
//
///**
// * conversion
// *
// * @param request
// * @return
// */
//public abstract DataSourcePageQueryParam request2paramAccess(CommonPageQueryRequest request);
///**
// * conversion
// *
// * @param dto
// * @return
// */
//public abstract DataSourcePageQueryVO dto2vo(DataSource dto);
//
///**
// * 参数转换
// *
// * @param request
// * @return
// */
//@Mappings({
// @Mapping(source = "user", target = "userName")
//})
//public abstract DataSourceCreateParam createReq2param(UserCreateRequest request);
//
///**
// * 参数转换
// *
// * @param request
// * @return
// */
//@Mappings({
// @Mapping(source = "user", target = "userName")
//})
//public abstract DataSourceUpdateParam updateReq2param(DataSourceUpdateRequest request);
}