Merge branch 'master' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/activiti

 Conflicts:
	sql/ruoyi-vue-pro.sql
	yudao-admin-server/src/main/resources/application.yaml
	yudao-admin-server/src/main/resources/mybatis-config/mybatis-config.xml
	yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/LoginUser.java
	yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java
This commit is contained in:
YunaiV
2021-12-30 19:58:31 +08:00
700 changed files with 58868 additions and 1158 deletions

View File

@@ -1,9 +0,0 @@
package cn.iocoder.yudao.adminserver.framework.async.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
@Configuration
@EnableAsync
public class AsyncConfiguration {
}

View File

@@ -1,4 +0,0 @@
/**
* 异步执行,基于 Spring @Async 实现
*/
package cn.iocoder.yudao.adminserver.framework.async;

View File

@@ -22,9 +22,11 @@ public class SecurityConfiguration {
@Bean
public Customizer<ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer() {
return registry -> {
// 通用的接口,可匿名访问 TODO 芋艿:需要抽象出去
// 验证码的接口
registry.antMatchers(api("/system/captcha/**")).anonymous();
// Spring Boot Admin Server 的安全配置 TODO 芋艿:需要抽象出去
// 获得租户编号的接口
registry.antMatchers(api("/system/tenant/get-id-by-name")).anonymous();
// Spring Boot Admin Server 的安全配置
registry.antMatchers(adminSeverContextPath).anonymous()
.antMatchers(adminSeverContextPath + "/**").anonymous();
// 短信回调 API

View File

@@ -10,6 +10,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.adminserver.modules.infra.convert.file.InfFileConvert;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
@@ -64,6 +65,7 @@ public class InfFileController {
@ApiOperation("下载文件")
@ApiImplicitParam(name = "path", value = "文件附件", required = true, dataTypeClass = MultipartFile.class)
public void getFile(HttpServletResponse response, @PathVariable("path") String path) throws IOException {
TenantContextHolder.setNullTenantId();
InfFileDO file = fileCoreService.getFile(path);
if (file == null) {
log.warn("[getFile][path({}) 文件不存在]", path);

View File

@@ -1,13 +1,13 @@
package cn.iocoder.yudao.adminserver.modules.infra.mq.message.config;
import cn.iocoder.yudao.framework.mq.core.pubsub.ChannelMessage;
import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
import lombok.Data;
/**
* 配置数据刷新 Message
*/
@Data
public class InfConfigRefreshMessage implements ChannelMessage {
public class InfConfigRefreshMessage extends AbstractChannelMessage {
@Override
public String getChannel() {

View File

@@ -1,8 +1,7 @@
package cn.iocoder.yudao.adminserver.modules.infra.mq.producer.config;
import cn.iocoder.yudao.adminserver.modules.infra.mq.message.config.InfConfigRefreshMessage;
import cn.iocoder.yudao.framework.mq.core.util.RedisMessageUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@@ -14,14 +13,14 @@ import javax.annotation.Resource;
public class InfConfigProducer {
@Resource
private StringRedisTemplate stringRedisTemplate;
private RedisMQTemplate redisMQTemplate;
/**
* 发送 {@link InfConfigRefreshMessage} 消息
*/
public void sendConfigRefreshMessage() {
InfConfigRefreshMessage message = new InfConfigRefreshMessage();
RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
redisMQTemplate.send(message);
}
}

View File

@@ -1,21 +1,25 @@
### 请求 /login 接口 => 成功
POST {{baseUrl}}/login
Content-Type: application/json
tenant-id: 1
{
"username": "admin",
"password": "admin123",
"uuid": "9b2ffbc1-7425-4155-9894-9d5c08541d62",
"uuid": "3acd87a09a4f48fb9118333780e94883",
"code": "1024"
}
### 请求 /get-permission-info 接口 => 成功
GET {{baseUrl}}/get-permission-info
Authorization: Bearer {{token}}
tenant-id: 1
### 请求 /list-menus 接口 => 成功
GET {{baseUrl}}/list-menus
Authorization: Bearer {{token}}
#Authorization: Bearer a6aa7714a2e44c95aaa8a2c5adc2a67a
tenant-id: 1
### 请求 /druid/xxx 接口 => 失败 TODO 临时测试
GET http://127.0.0.1:8080/druid/123

View File

@@ -9,7 +9,7 @@ import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysAuthService;
import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialService;
import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService;
import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
@@ -50,7 +50,7 @@ public class SysAuthController {
@Resource
private SysPermissionService permissionService;
@Resource
private SysSocialService socialService;
private SysSocialCoreService socialCoreService;
@PostMapping("/login")
@ApiOperation("使用账号密码登录")
@@ -102,7 +102,7 @@ public class SysAuthController {
})
public CommonResult<String> socialAuthRedirect(@RequestParam("type") Integer type,
@RequestParam("redirectUri") String redirectUri) {
return CommonResult.success(socialService.getAuthorizeUrl(type, redirectUri));
return CommonResult.success(socialCoreService.getAuthorizeUrl(type, redirectUri));
}
@PostMapping("/social-login")
@@ -133,7 +133,7 @@ public class SysAuthController {
@DeleteMapping("/social-unbind")
@ApiOperation("取消社交绑定")
public CommonResult<Boolean> socialUnbind(@RequestBody SysAuthSocialUnbindReqVO reqVO) {
socialService.unbindSocialUser(getLoginUserId(), reqVO.getType(), reqVO.getUnionId(), UserTypeEnum.ADMIN);
socialCoreService.unbindSocialUser(getLoginUserId(), reqVO.getType(), reqVO.getUnionId(), UserTypeEnum.ADMIN);
return CommonResult.success(true);
}

View File

@@ -0,0 +1,106 @@
package cn.iocoder.yudao.adminserver.modules.system.controller.tenant;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.*;
import cn.iocoder.yudao.adminserver.modules.system.convert.tenant.SysTenantConvert;
import cn.iocoder.yudao.adminserver.modules.system.service.tenant.SysTenantService;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
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.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@Api(tags = "租户")
@RestController
@RequestMapping("/system/tenant")
public class SysTenantController {
@Resource
private SysTenantService tenantService;
@GetMapping("/get-id-by-name")
@ApiOperation(value = "使用租户名,获得租户编号", notes = "登录界面,根据用户的租户名,获得租户编号")
@ApiImplicitParam(name = "name", value = "租户名", required = true, example = "芋道源码", dataTypeClass = Long.class)
public CommonResult<Long> getTenantIdByName(@RequestParam("name") String name) {
SysTenantDO tenantDO = tenantService.getTenantByName(name);
return success(tenantDO != null ? tenantDO.getId() : null);
}
@PostMapping("/create")
@ApiOperation("创建租户")
@PreAuthorize("@ss.hasPermission('system:tenant:create')")
public CommonResult<Long> createTenant(@Valid @RequestBody SysTenantCreateReqVO createReqVO) {
return success(tenantService.createTenant(createReqVO));
}
@PutMapping("/update")
@ApiOperation("更新租户")
@PreAuthorize("@ss.hasPermission('system:tenant:update')")
public CommonResult<Boolean> updateTenant(@Valid @RequestBody SysTenantUpdateReqVO updateReqVO) {
tenantService.updateTenant(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@ApiOperation("删除租户")
@ApiImplicitParam(name = "id", value = "编号", required = true)
@PreAuthorize("@ss.hasPermission('system:tenant:delete')")
public CommonResult<Boolean> deleteTenant(@RequestParam("id") Long id) {
tenantService.deleteTenant(id);
return success(true);
}
@GetMapping("/get")
@ApiOperation("获得租户")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('system:tenant:query')")
public CommonResult<SysTenantRespVO> getTenant(@RequestParam("id") Long id) {
SysTenantDO tenant = tenantService.getTenant(id);
return success(SysTenantConvert.INSTANCE.convert(tenant));
}
@GetMapping("/list")
@ApiOperation("获得租户列表")
@ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
@PreAuthorize("@ss.hasPermission('system:tenant:query')")
public CommonResult<List<SysTenantRespVO>> getTenantList(@RequestParam("ids") Collection<Long> ids) {
List<SysTenantDO> list = tenantService.getTenantList(ids);
return success(SysTenantConvert.INSTANCE.convertList(list));
}
@GetMapping("/page")
@ApiOperation("获得租户分页")
@PreAuthorize("@ss.hasPermission('system:tenant:query')")
public CommonResult<PageResult<SysTenantRespVO>> getTenantPage(@Valid SysTenantPageReqVO pageVO) {
PageResult<SysTenantDO> pageResult = tenantService.getTenantPage(pageVO);
return success(SysTenantConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/export-excel")
@ApiOperation("导出租户 Excel")
@PreAuthorize("@ss.hasPermission('system:tenant:export')")
@OperateLog(type = EXPORT)
public void exportTenantExcel(@Valid SysTenantExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<SysTenantDO> list = tenantService.getTenantList(exportReqVO);
// 导出 Excel
List<SysTenantExcelVO> datas = SysTenantConvert.INSTANCE.convertList02(list);
ExcelUtils.write(response, "租户.xls", "数据", SysTenantExcelVO.class, datas);
}
}

View File

@@ -0,0 +1,30 @@
package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
/**
* 租户 Base VO提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class SysTenantBaseVO {
@ApiModelProperty(value = "租户名", required = true, example = "芋道")
@NotNull(message = "租户名不能为空")
private String name;
@ApiModelProperty(value = "联系人", required = true, example = "芋艿")
@NotNull(message = "联系人不能为空")
private String contactName;
@ApiModelProperty(value = "联系手机", example = "15601691300")
private String contactMobile;
@ApiModelProperty(value = "租户状态0正常 1停用", required = true, example = "1")
@NotNull(message = "租户状态0正常 1停用不能为空")
private Integer status;
}

View File

@@ -0,0 +1,14 @@
package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.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 SysTenantCreateReqVO extends SysTenantBaseVO {
}

View File

@@ -0,0 +1,39 @@
package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import com.alibaba.excel.annotation.ExcelProperty;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
/**
* 租户 Excel VO
*
* @author 芋道源码
*/
@Data
public class SysTenantExcelVO {
@ExcelProperty("租户编号")
private Long id;
@ExcelProperty("租户名")
private String name;
@ExcelProperty("联系人")
private String contactName;
@ExcelProperty("联系手机")
private String contactMobile;
@ExcelProperty(value = "租户状态0正常 1停用", converter = DictConvert.class)
@DictFormat("sys_common_status") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中
private Integer status;
@ExcelProperty("创建时间")
private Date createTime;
}

View File

@@ -0,0 +1,36 @@
package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel(value = "租户 Excel 导出 Request VO", description = "参数和 SysTenantPageReqVO 是一致的")
@Data
public class SysTenantExportReqVO {
@ApiModelProperty(value = "租户名", example = "芋道")
private String name;
@ApiModelProperty(value = "联系人", example = "芋艿")
private String contactName;
@ApiModelProperty(value = "联系手机", example = "15601691300")
private String contactMobile;
@ApiModelProperty(value = "租户状态0正常 1停用", example = "1")
private Integer status;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@@ -0,0 +1,41 @@
package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("租户分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SysTenantPageReqVO extends PageParam {
@ApiModelProperty(value = "租户名", example = "芋道")
private String name;
@ApiModelProperty(value = "联系人", example = "芋艿")
private String contactName;
@ApiModelProperty(value = "联系手机", example = "15601691300")
private String contactMobile;
@ApiModelProperty(value = "租户状态0正常 1停用", example = "1")
private Integer status;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@@ -0,0 +1,19 @@
package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
@ApiModel("租户 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SysTenantRespVO extends SysTenantBaseVO {
@ApiModelProperty(value = "租户编号", required = true, example = "1024")
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}

View File

@@ -0,0 +1,18 @@
package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.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 SysTenantUpdateReqVO extends SysTenantBaseVO {
@ApiModelProperty(value = "租户编号", required = true, example = "1024")
@NotNull(message = "租户编号不能为空")
private Long id;
}

View File

@@ -1,3 +1,4 @@
### 请求 /system/user/page 接口 => 没有权限
GET {{baseUrl}}/system/user/page?pageNo=1&pageSize=10
Authorization: Bearer test104 # 使用测试账号
Authorization: Bearer test1 # 使用测试账号
tenant-id: 1

View File

@@ -15,7 +15,7 @@ import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleSer
import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialService;
import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService;
import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
@@ -56,7 +56,7 @@ public class SysUserProfileController {
@Resource
private SysRoleService roleService;
@Resource
private SysSocialService socialService;
private SysSocialCoreService socialService;
@GetMapping("/get")
@ApiOperation("获得登录用户信息")

View File

@@ -0,0 +1,36 @@
package cn.iocoder.yudao.adminserver.modules.system.convert.tenant;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantCreateReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantExcelVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantRespVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantUpdateReqVO;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* 租户 Convert
*
* @author 芋道源码
*/
@Mapper
public interface SysTenantConvert {
SysTenantConvert INSTANCE = Mappers.getMapper(SysTenantConvert.class);
SysTenantDO convert(SysTenantCreateReqVO bean);
SysTenantDO convert(SysTenantUpdateReqVO bean);
SysTenantRespVO convert(SysTenantDO bean);
List<SysTenantRespVO> convertList(List<SysTenantDO> list);
PageResult<SysTenantRespVO> convertPage(PageResult<SysTenantDO> page);
List<SysTenantExcelVO> convertList02(List<SysTenantDO> list);
}

View File

@@ -1,7 +1,7 @@
package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@@ -15,7 +15,7 @@ import lombok.EqualsAndHashCode;
@TableName("sys_dept")
@Data
@EqualsAndHashCode(callSuper = true)
public class SysDeptDO extends BaseDO {
public class SysDeptDO extends TenantBaseDO {
/**
* 部门ID

View File

@@ -1,7 +1,7 @@
package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@@ -15,14 +15,13 @@ import lombok.EqualsAndHashCode;
@TableName("sys_post")
@Data
@EqualsAndHashCode(callSuper = true)
public class SysPostDO extends BaseDO {
public class SysPostDO extends TenantBaseDO {
/**
* 岗位序号
*/
@TableId
private Long id;
/**
* 岗位名称
*/

View File

@@ -3,7 +3,7 @@ package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@@ -22,7 +22,7 @@ import java.util.Map;
@TableName(value = "sys_operate_log", autoResultMap = true)
@Data
@EqualsAndHashCode(callSuper = true)
public class SysOperateLogDO extends BaseDO {
public class SysOperateLogDO extends TenantBaseDO {
/**
* {@link #javaMethodArgs} 的最大长度

View File

@@ -1,8 +1,8 @@
package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.notice;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.adminserver.modules.system.enums.notice.SysNoticeTypeEnum;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@@ -16,7 +16,7 @@ import lombok.EqualsAndHashCode;
@TableName("sys_notice")
@Data
@EqualsAndHashCode(callSuper = true)
public class SysNoticeDO extends BaseDO {
public class SysNoticeDO extends TenantBaseDO {
/**
* 公告ID

View File

@@ -24,7 +24,7 @@ public interface SysDeptMapper extends BaseMapperX<SysDeptDO> {
}
default Integer selectCountByParentId(Long parentId) {
return selectCount(new QueryWrapper<SysDeptDO>().eq("parent_id", parentId));
return selectCount("parent_id", parentId);
}
default boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) {

View File

@@ -19,7 +19,7 @@ public interface SysMenuMapper extends BaseMapperX<SysMenuDO> {
}
default Integer selectCountByParentId(Long parentId) {
return selectCount(new QueryWrapper<SysMenuDO>().eq("parent_id", parentId));
return selectCount("parent_id", parentId);
}
default List<SysMenuDO> selectList(SysMenuListReqVO reqVO) {

View File

@@ -0,0 +1,44 @@
package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.tenant;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantExportReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantPageReqVO;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* 租户 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface SysTenantMapper extends BaseMapperX<SysTenantDO> {
default PageResult<SysTenantDO> selectPage(SysTenantPageReqVO reqVO) {
return selectPage(reqVO, new QueryWrapperX<SysTenantDO>()
.likeIfPresent("name", reqVO.getName())
.likeIfPresent("contact_name", reqVO.getContactName())
.likeIfPresent("contact_mobile", reqVO.getContactMobile())
.eqIfPresent("status", reqVO.getStatus())
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
.orderByDesc("id"));
}
default List<SysTenantDO> selectList(SysTenantExportReqVO reqVO) {
return selectList(new QueryWrapperX<SysTenantDO>()
.likeIfPresent("name", reqVO.getName())
.likeIfPresent("contact_name", reqVO.getContactName())
.likeIfPresent("contact_mobile", reqVO.getContactMobile())
.eqIfPresent("status", reqVO.getStatus())
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
.orderByDesc("id"));
}
default SysTenantDO selectByName(String name) {
return selectOne("name", name);
}
}

View File

@@ -85,10 +85,12 @@ public interface SysErrorCodeConstants {
ErrorCode SMS_TEMPLATE_NOT_EXISTS = new ErrorCode(1002011000, "短信模板不存在");
ErrorCode SMS_TEMPLATE_CODE_DUPLICATE = new ErrorCode(1002011001, "已经存在编码为【{}】的短信模板");
// ========== 租户模块 1002012000 ==========
ErrorCode TENANT_NOT_EXISTS = new ErrorCode(1002012000, "租户不存在");
// ========== 错误码模块 1002013000 ==========
ErrorCode ERROR_CODE_NOT_EXISTS = new ErrorCode(1002013000, "错误码不存在");
ErrorCode ERROR_CODE_DUPLICATE = new ErrorCode(1002013001, "已经存在编码为【{}】的错误码");
}

View File

@@ -12,6 +12,13 @@ import java.time.Duration;
@Data
public class CaptchaProperties {
private static final Boolean ENABLE_DEFAULT = true;
/**
* 是否开启
* 注意,这里仅仅是后端 Server 是否校验,暂时不控制前端的逻辑
*/
private Boolean enable = ENABLE_DEFAULT;
/**
* 验证码的过期时间
*/

View File

@@ -0,0 +1,25 @@
package cn.iocoder.yudao.adminserver.modules.system.framework.datapermission.config;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
import cn.iocoder.yudao.framework.datapermission.core.dept.rule.DeptDataPermissionRuleCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* system 模块的数据权限 Configuration
*
* @author 芋道源码
*/
@Configuration
public class SysDataPermissionConfiguration {
@Bean
public DeptDataPermissionRuleCustomizer sysDeptDataPermissionRuleCustomizer() {
return rule -> {
rule.addDeptColumn(SysUserDO.class);
rule.addDeptColumn(SysDeptDO.class, "id");
};
}
}

View File

@@ -0,0 +1,4 @@
/**
* system 模块的数据权限配置
*/
package cn.iocoder.yudao.adminserver.modules.system.framework.datapermission;

View File

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.adminserver.modules.system.job.auth;
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService;
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@@ -13,6 +14,7 @@ import javax.annotation.Resource;
* @author 願
*/
@Component
@TenantJob
@Slf4j
public class SysUserSessionTimeoutJob implements JobHandler {

View File

@@ -1,13 +1,17 @@
package cn.iocoder.yudao.adminserver.modules.system.mq.message.dept;
import cn.iocoder.yudao.framework.mq.core.pubsub.ChannelMessage;
import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 部门数据刷新 Message
*
* @author 芋道源码
*/
@Data
public class SysDeptRefreshMessage implements ChannelMessage {
@EqualsAndHashCode(callSuper = true)
public class SysDeptRefreshMessage extends AbstractChannelMessage {
@Override
public String getChannel() {

View File

@@ -1,13 +1,15 @@
package cn.iocoder.yudao.adminserver.modules.system.mq.message.dict;
import cn.iocoder.yudao.framework.mq.core.pubsub.ChannelMessage;
import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 字典数据数据刷新 Message
*/
@Data
public class SysDictDataRefreshMessage implements ChannelMessage {
@EqualsAndHashCode(callSuper = true)
public class SysDictDataRefreshMessage extends AbstractChannelMessage {
@Override
public String getChannel() {

View File

@@ -1,7 +1,8 @@
package cn.iocoder.yudao.adminserver.modules.system.mq.message.mail;
import cn.iocoder.yudao.framework.mq.core.stream.StreamMessage;
import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessage;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotNull;
import java.util.Map;
@@ -12,7 +13,8 @@ import java.util.Map;
* @author 芋道源码
*/
@Data
public class SysMailSendMessage implements StreamMessage {
@EqualsAndHashCode(callSuper = true)
public class SysMailSendMessage extends AbstractStreamMessage {
/**
* 邮箱地址

View File

@@ -1,13 +1,17 @@
package cn.iocoder.yudao.adminserver.modules.system.mq.message.permission;
import cn.iocoder.yudao.framework.mq.core.pubsub.ChannelMessage;
import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 菜单数据刷新 Message
*
* @author 芋道源码
*/
@Data
public class SysMenuRefreshMessage implements ChannelMessage {
@EqualsAndHashCode(callSuper = true)
public class SysMenuRefreshMessage extends AbstractChannelMessage {
@Override
public String getChannel() {

View File

@@ -1,13 +1,17 @@
package cn.iocoder.yudao.adminserver.modules.system.mq.message.permission;
import cn.iocoder.yudao.framework.mq.core.pubsub.ChannelMessage;
import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 角色与菜单数据刷新 Message
*
* @author 芋道源码
*/
@Data
public class SysRoleMenuRefreshMessage implements ChannelMessage {
@EqualsAndHashCode(callSuper = true)
public class SysRoleMenuRefreshMessage extends AbstractChannelMessage {
@Override
public String getChannel() {

View File

@@ -1,13 +1,17 @@
package cn.iocoder.yudao.adminserver.modules.system.mq.message.permission;
import cn.iocoder.yudao.framework.mq.core.pubsub.ChannelMessage;
import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 角色数据刷新 Message
*
* @author 芋道源码
*/
@Data
public class SysRoleRefreshMessage implements ChannelMessage {
@EqualsAndHashCode(callSuper = true)
public class SysRoleRefreshMessage extends AbstractChannelMessage {
@Override
public String getChannel() {

View File

@@ -1,13 +1,17 @@
package cn.iocoder.yudao.adminserver.modules.system.mq.message.sms;
import cn.iocoder.yudao.framework.mq.core.pubsub.ChannelMessage;
import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 短信渠道的数据刷新 Message
*
* @author 芋道源码
*/
@Data
public class SysSmsChannelRefreshMessage implements ChannelMessage {
@EqualsAndHashCode(callSuper = true)
public class SysSmsChannelRefreshMessage extends AbstractChannelMessage {
@Override
public String getChannel() {

View File

@@ -1,13 +1,17 @@
package cn.iocoder.yudao.adminserver.modules.system.mq.message.sms;
import cn.iocoder.yudao.framework.mq.core.pubsub.ChannelMessage;
import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 短信模板的数据刷新 Message
*
* @author 芋道源码
*/
@Data
public class SysSmsTemplateRefreshMessage implements ChannelMessage {
@EqualsAndHashCode(callSuper = true)
public class SysSmsTemplateRefreshMessage extends AbstractChannelMessage {
@Override
public String getChannel() {

View File

@@ -1,8 +1,7 @@
package cn.iocoder.yudao.adminserver.modules.system.mq.producer.dept;
import cn.iocoder.yudao.framework.mq.core.util.RedisMessageUtils;
import cn.iocoder.yudao.adminserver.modules.system.mq.message.dept.SysDeptRefreshMessage;
import org.springframework.data.redis.core.StringRedisTemplate;
import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@@ -14,14 +13,14 @@ import javax.annotation.Resource;
public class SysDeptProducer {
@Resource
private StringRedisTemplate stringRedisTemplate;
private RedisMQTemplate redisMQTemplate;
/**
* 发送 {@link SysDeptRefreshMessage} 消息
*/
public void sendDeptRefreshMessage() {
SysDeptRefreshMessage message = new SysDeptRefreshMessage();
RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
redisMQTemplate.send(message);
}
}

View File

@@ -1,8 +1,7 @@
package cn.iocoder.yudao.adminserver.modules.system.mq.producer.dict;
import cn.iocoder.yudao.framework.mq.core.util.RedisMessageUtils;
import cn.iocoder.yudao.adminserver.modules.system.mq.message.dict.SysDictDataRefreshMessage;
import org.springframework.data.redis.core.StringRedisTemplate;
import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@@ -14,14 +13,14 @@ import javax.annotation.Resource;
public class SysDictDataProducer {
@Resource
private StringRedisTemplate stringRedisTemplate;
private RedisMQTemplate redisMQTemplate;
/**
* 发送 {@link SysDictDataRefreshMessage} 消息
*/
public void sendDictDataRefreshMessage() {
SysDictDataRefreshMessage message = new SysDictDataRefreshMessage();
RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
redisMQTemplate.send(message);
}
}

View File

@@ -1,8 +1,7 @@
package cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission;
import cn.iocoder.yudao.framework.mq.core.util.RedisMessageUtils;
import cn.iocoder.yudao.adminserver.modules.system.mq.message.permission.SysMenuRefreshMessage;
import org.springframework.data.redis.core.StringRedisTemplate;
import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@@ -14,14 +13,14 @@ import javax.annotation.Resource;
public class SysMenuProducer {
@Resource
private StringRedisTemplate stringRedisTemplate;
private RedisMQTemplate redisMQTemplate;
/**
* 发送 {@link SysMenuRefreshMessage} 消息
*/
public void sendMenuRefreshMessage() {
SysMenuRefreshMessage message = new SysMenuRefreshMessage();
RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
redisMQTemplate.send(message);
}
}

View File

@@ -1,8 +1,7 @@
package cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission;
import cn.iocoder.yudao.framework.mq.core.util.RedisMessageUtils;
import cn.iocoder.yudao.adminserver.modules.system.mq.message.permission.SysRoleMenuRefreshMessage;
import org.springframework.data.redis.core.StringRedisTemplate;
import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@@ -14,14 +13,14 @@ import javax.annotation.Resource;
public class SysPermissionProducer {
@Resource
private StringRedisTemplate stringRedisTemplate;
private RedisMQTemplate redisMQTemplate;
/**
* 发送 {@link SysRoleMenuRefreshMessage} 消息
*/
public void sendRoleMenuRefreshMessage() {
SysRoleMenuRefreshMessage message = new SysRoleMenuRefreshMessage();
RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
redisMQTemplate.send(message);
}
}

View File

@@ -1,8 +1,7 @@
package cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission;
import cn.iocoder.yudao.framework.mq.core.util.RedisMessageUtils;
import cn.iocoder.yudao.adminserver.modules.system.mq.message.permission.SysRoleRefreshMessage;
import org.springframework.data.redis.core.StringRedisTemplate;
import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@@ -16,14 +15,14 @@ import javax.annotation.Resource;
public class SysRoleProducer {
@Resource
private StringRedisTemplate stringRedisTemplate;
private RedisMQTemplate redisMQTemplate;
/**
* 发送 {@link SysRoleRefreshMessage} 消息
*/
public void sendRoleRefreshMessage() {
SysRoleRefreshMessage message = new SysRoleRefreshMessage();
RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
redisMQTemplate.send(message);
}
}

View File

@@ -1,15 +1,12 @@
package cn.iocoder.yudao.adminserver.modules.system.mq.producer.sms;
import cn.iocoder.yudao.framework.common.core.KeyValue;
import cn.iocoder.yudao.framework.mq.core.util.RedisMessageUtils;
import cn.iocoder.yudao.adminserver.modules.system.mq.message.sms.SysSmsChannelRefreshMessage;
import cn.iocoder.yudao.adminserver.modules.system.mq.message.sms.SysSmsTemplateRefreshMessage;
import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
/**
* Sms 短信相关消息的 Producer
@@ -22,14 +19,14 @@ import java.util.List;
public class SysSmsProducer {
@Resource
private StringRedisTemplate stringRedisTemplate;
private RedisMQTemplate redisMQTemplate;
/**
* 发送 {@link SysSmsChannelRefreshMessage} 消息
*/
public void sendSmsChannelRefreshMessage() {
SysSmsChannelRefreshMessage message = new SysSmsChannelRefreshMessage();
RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
redisMQTemplate.send(message);
}
/**
@@ -37,7 +34,7 @@ public class SysSmsProducer {
*/
public void sendSmsTemplateRefreshMessage() {
SysSmsTemplateRefreshMessage message = new SysSmsTemplateRefreshMessage();
RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
redisMQTemplate.send(message);
}
}

View File

@@ -1,21 +1,17 @@
package cn.iocoder.yudao.adminserver.modules.system.service.auth.impl;
import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService;
import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysPostService;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialBindReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLogin2ReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLoginReqVO;
import cn.iocoder.yudao.adminserver.modules.system.convert.auth.SysAuthConvert;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysPostDO;
import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginLogTypeEnum;
import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum;
import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysAuthService;
import cn.iocoder.yudao.adminserver.modules.system.service.common.SysCaptchaService;
import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysPostService;
import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO;
@@ -23,7 +19,7 @@ import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO
import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService;
import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService;
import cn.iocoder.yudao.coreservice.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialService;
import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService;
import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
@@ -45,16 +41,14 @@ import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*;
import static java.util.Collections.EMPTY_LIST;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static java.util.Collections.singleton;
/**
@@ -66,6 +60,8 @@ import static java.util.Collections.singleton;
@Slf4j
public class SysAuthServiceImpl implements SysAuthService {
private static final UserTypeEnum USER_TYPE_ENUM = UserTypeEnum.ADMIN;
@Resource
@Lazy // 延迟加载,因为存在相互依赖的问题
private AuthenticationManager authenticationManager;
@@ -83,11 +79,10 @@ public class SysAuthServiceImpl implements SysAuthService {
@Resource
private SysUserSessionCoreService userSessionCoreService;
@Resource
private SysPostService sysPostService;
private SysSocialService socialService;
private SysPostService postService;
@Resource
private SysSocialCoreService socialService;
// TODO @timfruit静态枚举类需要都大写例如说 USER_TYPE_ENUM静态变量放在普通变量前面这个实践不错哈。
private static final UserTypeEnum userTypeEnum = UserTypeEnum.ADMIN;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
@@ -97,9 +92,7 @@ public class SysAuthServiceImpl implements SysAuthService {
throw new UsernameNotFoundException(username);
}
// 创建 LoginUser 对象
LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user);
loginUser.setPostIds(user.getPostIds());
return loginUser;
return this.buildLoginUser(user);
}
@Override
@@ -112,9 +105,7 @@ public class SysAuthServiceImpl implements SysAuthService {
this.createLoginLog(user.getUsername(), SysLoginLogTypeEnum.LOGIN_MOCK, SysLoginResultEnum.SUCCESS);
// 创建 LoginUser 对象
LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user);
loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
return loginUser;
return this.buildLoginUser(user);
}
@Override
@@ -122,25 +113,28 @@ public class SysAuthServiceImpl implements SysAuthService {
// 判断验证码是否正确
this.verifyCaptcha(reqVO.getUsername(), reqVO.getUuid(), reqVO.getCode());
// 使用账号密码,进行登录
// 使用账号密码,进行登录
LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword());
loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
loginUser.setGroups(this.getUserPosts(loginUser.getPostIds()));
// 缓存登陆用户到 Redis 中,返回 sessionId 编号
return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
}
private List<String> getUserPosts(Set<Long> postIds) {
return Optional.ofNullable(postIds).map(ids->
sysPostService.getPosts(ids).stream().map(post -> post.getCode()).collect(Collectors.toList())
).orElse(EMPTY_LIST);
if (CollUtil.isEmpty(postIds)) {
return Collections.emptyList();
}
return convertList(postService.getPosts(postIds), SysPostDO::getCode);
}
private void verifyCaptcha(String username, String captchaUUID, String captchaCode) {
// 如果验证码关闭,则不进行校验
if (!captchaService.isCaptchaEnable()) {
return;
}
// 验证码不存在
final SysLoginLogTypeEnum logTypeEnum = SysLoginLogTypeEnum.LOGIN_USERNAME;
String code = captchaService.getCaptchaCode(captchaUUID);
// 验证码不存在
if (code == null) {
// 创建登录失败日志(验证码不存在)
this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.CAPTCHA_NOT_FOUND);
@@ -222,7 +216,7 @@ public class SysAuthServiceImpl implements SysAuthService {
// 如果未绑定 SysSocialUserDO 用户,则无法自动登录,进行报错
String unionId = socialService.getAuthUserUnionId(authUser);
List<SysSocialUserDO> socialUsers = socialService.getAllSocialUserList(reqVO.getType(), unionId, userTypeEnum);
List<SysSocialUserDO> socialUsers = socialService.getAllSocialUserList(reqVO.getType(), unionId, USER_TYPE_ENUM);
if (CollUtil.isEmpty(socialUsers)) {
throw exception(AUTH_THIRD_LOGIN_NOT_BIND);
}
@@ -235,11 +229,10 @@ public class SysAuthServiceImpl implements SysAuthService {
this.createLoginLog(user.getUsername(), SysLoginLogTypeEnum.LOGIN_SOCIAL, SysLoginResultEnum.SUCCESS);
// 创建 LoginUser 对象
LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user);
loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
LoginUser loginUser = this.buildLoginUser(user);
// 绑定社交用户(更新)
socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, userTypeEnum);
socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, USER_TYPE_ENUM);
// 缓存登录用户到 Redis 中,返回 sessionId 编号
return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
@@ -253,10 +246,9 @@ public class SysAuthServiceImpl implements SysAuthService {
// 使用账号密码,进行登录。
LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword());
loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
// 绑定社交用户(新增)
socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, userTypeEnum);
socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, USER_TYPE_ENUM);
// 缓存登录用户到 Redis 中,返回 sessionId 编号
return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
@@ -269,7 +261,7 @@ public class SysAuthServiceImpl implements SysAuthService {
Assert.notNull(authUser, "授权用户不为空");
// 绑定社交用户(新增)
socialService.bindSocialUser(userId, reqVO.getType(), authUser, userTypeEnum);
socialService.bindSocialUser(userId, reqVO.getType(), authUser, USER_TYPE_ENUM);
}
@Override
@@ -290,7 +282,7 @@ public class SysAuthServiceImpl implements SysAuthService {
reqDTO.setLogType(SysLoginLogTypeEnum.LOGOUT_SELF.getType());
reqDTO.setTraceId(TracerUtils.getTraceId());
reqDTO.setUserId(userId);
reqDTO.setUserType(userTypeEnum.getValue());
reqDTO.setUserType(USER_TYPE_ENUM.getValue());
reqDTO.setUsername(username);
reqDTO.setUserAgent(ServletUtils.getUserAgent());
reqDTO.setUserIp(ServletUtils.getClientIP());
@@ -306,15 +298,14 @@ public class SysAuthServiceImpl implements SysAuthService {
return null;
}
// 刷新 LoginUser 缓存
this.refreshLoginUserCache(token, loginUser);
return loginUser;
return this.refreshLoginUserCache(token, loginUser);
}
private void refreshLoginUserCache(String token, LoginUser loginUser) {
private LoginUser refreshLoginUserCache(String token, LoginUser loginUser) {
// 每 1/3 的 Session 超时时间,刷新 LoginUser 缓存
if (System.currentTimeMillis() - loginUser.getUpdateTime().getTime() <
userSessionCoreService.getSessionTimeoutMillis() / 3) {
return;
return loginUser;
}
// 重新加载 SysUserDO 信息
@@ -324,9 +315,18 @@ public class SysAuthServiceImpl implements SysAuthService {
}
// 刷新 LoginUser 缓存
LoginUser newLoginUser= this.buildLoginUser(user);
userSessionCoreService.refreshUserSession(token, newLoginUser);
return newLoginUser;
}
private LoginUser buildLoginUser(SysUserDO user) {
LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user);
// 补全字段
loginUser.setDeptId(user.getDeptId());
loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId()));
userSessionCoreService.refreshUserSession(token, loginUser);
loginUser.setGroups(this.getUserPosts(user.getPostIds()));
return loginUser;
}
}

View File

@@ -14,6 +14,13 @@ public interface SysCaptchaService {
*/
SysCaptchaImageRespVO getCaptchaImage();
/**
* 是否开启图片验证码
*
* @return 是否
*/
Boolean isCaptchaEnable();
/**
* 获得 uuid 对应的验证码
*

View File

@@ -35,6 +35,11 @@ public class SysCaptchaServiceImpl implements SysCaptchaService {
return SysCaptchaConvert.INSTANCE.convert(uuid, captcha);
}
@Override
public Boolean isCaptchaEnable() {
return captchaProperties.getEnable();
}
@Override
public String getCaptchaCode(String uuid) {
return captchaRedisDAO.get(uuid);

View File

@@ -169,9 +169,12 @@ public class SysDeptServiceImpl implements SysDeptService {
@Override
public List<SysDeptDO> getDeptsByParentIdFromCache(Long parentId, boolean recursive) {
List<SysDeptDO> result = new ArrayList<>();
if (parentId == null) {
return Collections.emptyList();
}
List<SysDeptDO> result = new ArrayList<>(); // TODO 芋艿:待优化,新增缓存,避免每次遍历的计算
// 递归,简单粗暴
this.listDeptsByParentIdFromCache(result, parentId,
this.getDeptsByParentIdFromCache(result, parentId,
recursive ? Integer.MAX_VALUE : 1, // 如果递归获取,则无限;否则,只递归 1 次
parentDeptCache);
return result;
@@ -185,8 +188,8 @@ public class SysDeptServiceImpl implements SysDeptService {
* @param recursiveCount 递归次数
* @param parentDeptMap 父部门 Map使用缓存避免变化
*/
private void listDeptsByParentIdFromCache(List<SysDeptDO> result, Long parentId, int recursiveCount,
Multimap<Long, SysDeptDO> parentDeptMap) {
private void getDeptsByParentIdFromCache(List<SysDeptDO> result, Long parentId, int recursiveCount,
Multimap<Long, SysDeptDO> parentDeptMap) {
// 递归次数为 0结束
if (recursiveCount == 0) {
return;
@@ -198,7 +201,7 @@ public class SysDeptServiceImpl implements SysDeptService {
}
result.addAll(depts);
// 继续递归
depts.forEach(dept -> listDeptsByParentIdFromCache(result, dept.getId(),
depts.forEach(dept -> getDeptsByParentIdFromCache(result, dept.getId(),
recursiveCount - 1, parentDeptMap));
}
@@ -264,11 +267,4 @@ public class SysDeptServiceImpl implements SysDeptService {
}
}
// @Override
// @DataScope(deptAlias = "d")
// public List<SysDept> selectDeptList(SysDept dept)
// {
// return deptMapper.selectDeptList(dept);
// }
}

View File

@@ -1,5 +1,6 @@
package cn.iocoder.yudao.adminserver.modules.system.service.permission;
import cn.iocoder.yudao.framework.datapermission.core.dept.service.DeptDataPermissionFrameworkService;
import cn.iocoder.yudao.framework.security.core.service.SecurityPermissionFrameworkService;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysMenuDO;
import org.springframework.lang.Nullable;
@@ -15,7 +16,7 @@ import java.util.Set;
*
* @author 芋道源码
*/
public interface SysPermissionService extends SecurityPermissionFrameworkService {
public interface SysPermissionService extends SecurityPermissionFrameworkService, DeptDataPermissionFrameworkService {
/**
* 初始化权限的本地缓存

View File

@@ -3,19 +3,25 @@ package cn.iocoder.yudao.adminserver.modules.system.service.permission.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysRoleMenuMapper;
import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysUserRoleMapper;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysMenuDO;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleMenuDO;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysUserRoleDO;
import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysRoleMenuMapper;
import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysUserRoleMapper;
import cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission.SysPermissionProducer;
import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService;
import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysMenuService;
import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.enums.DataScopeEnum;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
@@ -39,6 +45,11 @@ import java.util.*;
@Slf4j
public class SysPermissionServiceImpl implements SysPermissionService {
/**
* LoginUser 的 Context 缓存 Key
*/
public static final String CONTEXT_KEY = SysPermissionServiceImpl.class.getSimpleName();
/**
* 定时执行 {@link #schedulePeriodicRefresh()} 的周期
* 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高
@@ -75,6 +86,8 @@ public class SysPermissionServiceImpl implements SysPermissionService {
private SysRoleService roleService;
@Resource
private SysMenuService menuService;
@Resource
private SysDeptService deptService;
@Resource
private SysPermissionProducer permissionProducer;
@@ -329,4 +342,58 @@ public class SysPermissionServiceImpl implements SysPermissionService {
return CollUtil.containsAny(userRoles, Sets.newHashSet(roles));
}
@Override
public DeptDataPermissionRespDTO getDeptDataPermission(LoginUser loginUser) {
// 判断是否 context 已经缓存
DeptDataPermissionRespDTO result = loginUser.getContext(CONTEXT_KEY, DeptDataPermissionRespDTO.class);
if (result != null) {
return result;
}
// 创建 DeptDataPermissionRespDTO 对象
result = new DeptDataPermissionRespDTO();
List<SysRoleDO> roles = roleService.getRolesFromCache(loginUser.getRoleIds());
for (SysRoleDO role : roles) {
// 为空时,跳过
if (role.getDataScope() == null) {
continue;
}
// 情况一ALL
if (Objects.equals(role.getDataScope(), DataScopeEnum.ALL.getScope())) {
result.setAll(true);
continue;
}
// 情况二DEPT_CUSTOM
if (Objects.equals(role.getDataScope(), DataScopeEnum.DEPT_CUSTOM.getScope())) {
CollUtil.addAll(result.getDeptIds(), role.getDataScopeDeptIds());
// 自定义可见部门时,保证可以看到自己所在的部门。否则,一些场景下可能会有问题。
// 例如说,登录时,基于 t_user 的 username 查询会可能被 dept_id 过滤掉
CollUtil.addAll(result.getDeptIds(), loginUser.getDeptId());
continue;
}
// 情况三DEPT_ONLY
if (Objects.equals(role.getDataScope(), DataScopeEnum.DEPT_ONLY.getScope())) {
CollectionUtils.addIfNotNull(result.getDeptIds(), loginUser.getDeptId());
continue;
}
// 情况四DEPT_DEPT_AND_CHILD
if (Objects.equals(role.getDataScope(), DataScopeEnum.DEPT_AND_CHILD.getScope())) {
List<SysDeptDO> depts = deptService.getDeptsByParentIdFromCache(loginUser.getDeptId(), true);
CollUtil.addAll(result.getDeptIds(), CollectionUtils.convertList(depts, SysDeptDO::getId));
continue;
}
// 情况五SELF
if (Objects.equals(role.getDataScope(), DataScopeEnum.SELF.getScope())) {
result.setSelf(true);
continue;
}
// 未知情况error log 即可
log.error("[getDeptDataPermission][LoginUser({}) role({}) 无法处理]", loginUser.getId(), JsonUtils.toJsonString(result));
}
// 添加到缓存,并返回
loginUser.setContext(CONTEXT_KEY, result);
return result;
}
}

View File

@@ -18,6 +18,7 @@ import cn.iocoder.yudao.adminserver.modules.system.enums.permission.SysRoleTypeE
import cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission.SysRoleProducer;
import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService;
import cn.iocoder.yudao.framework.security.core.enums.DataScopeEnum;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
import lombok.extern.slf4j.Slf4j;
@@ -127,6 +128,7 @@ public class SysRoleServiceImpl implements SysRoleService {
SysRoleDO role = SysRoleConvert.INSTANCE.convert(reqVO);
role.setType(SysRoleTypeEnum.CUSTOM.getType());
role.setStatus(CommonStatusEnum.ENABLE.getStatus());
role.setDataScope(DataScopeEnum.ALL.getScope()); // 默认可查看所有数据。原因是,可能一些项目不需要项目权限
roleMapper.insert(role);
// 发送刷新消息
roleProducer.sendRoleRefreshMessage();

View File

@@ -0,0 +1,83 @@
package cn.iocoder.yudao.adminserver.modules.system.service.tenant;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantCreateReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantExportReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantPageReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantUpdateReqVO;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import javax.validation.Valid;
import java.util.Collection;
import java.util.List;
/**
* 租户 Service 接口
*
* @author 芋道源码
*/
public interface SysTenantService {
/**
* 创建租户
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createTenant(@Valid SysTenantCreateReqVO createReqVO);
/**
* 更新租户
*
* @param updateReqVO 更新信息
*/
void updateTenant(@Valid SysTenantUpdateReqVO updateReqVO);
/**
* 删除租户
*
* @param id 编号
*/
void deleteTenant(Long id);
/**
* 获得租户
*
* @param id 编号
* @return 租户
*/
SysTenantDO getTenant(Long id);
/**
* 获得租户列表
*
* @param ids 编号
* @return 租户列表
*/
List<SysTenantDO> getTenantList(Collection<Long> ids);
/**
* 获得租户分页
*
* @param pageReqVO 分页查询
* @return 租户分页
*/
PageResult<SysTenantDO> getTenantPage(SysTenantPageReqVO pageReqVO);
/**
* 获得租户列表, 用于 Excel 导出
*
* @param exportReqVO 查询条件
* @return 租户列表
*/
List<SysTenantDO> getTenantList(SysTenantExportReqVO exportReqVO);
/**
* 获得名字对应的租户
*
* @param name 组户名
* @return 租户
*/
SysTenantDO getTenantByName(String name);
}

View File

@@ -0,0 +1,91 @@
package cn.iocoder.yudao.adminserver.modules.system.service.tenant.impl;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantCreateReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantExportReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantPageReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantUpdateReqVO;
import cn.iocoder.yudao.adminserver.modules.system.convert.tenant.SysTenantConvert;
import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.tenant.SysTenantMapper;
import cn.iocoder.yudao.adminserver.modules.system.service.tenant.SysTenantService;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.TENANT_NOT_EXISTS;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
/**
* 租户 Service 实现类
*
* @author 芋道源码
*/
@Service
@Validated
public class SysTenantServiceImpl implements SysTenantService {
@Resource
private SysTenantMapper tenantMapper;
@Override
public Long createTenant(SysTenantCreateReqVO createReqVO) {
// 插入
SysTenantDO tenant = SysTenantConvert.INSTANCE.convert(createReqVO);
tenantMapper.insert(tenant);
// 返回
return tenant.getId();
}
@Override
public void updateTenant(SysTenantUpdateReqVO updateReqVO) {
// 校验存在
this.validateTenantExists(updateReqVO.getId());
// 更新
SysTenantDO updateObj = SysTenantConvert.INSTANCE.convert(updateReqVO);
tenantMapper.updateById(updateObj);
}
@Override
public void deleteTenant(Long id) {
// 校验存在
this.validateTenantExists(id);
// 删除
tenantMapper.deleteById(id);
}
private void validateTenantExists(Long id) {
if (tenantMapper.selectById(id) == null) {
throw exception(TENANT_NOT_EXISTS);
}
}
@Override
public SysTenantDO getTenant(Long id) {
return tenantMapper.selectById(id);
}
@Override
public List<SysTenantDO> getTenantList(Collection<Long> ids) {
return tenantMapper.selectBatchIds(ids);
}
@Override
public PageResult<SysTenantDO> getTenantPage(SysTenantPageReqVO pageReqVO) {
return tenantMapper.selectPage(pageReqVO);
}
@Override
public List<SysTenantDO> getTenantList(SysTenantExportReqVO exportReqVO) {
return tenantMapper.selectList(exportReqVO);
}
@Override
public SysTenantDO getTenantByName(String name) {
return tenantMapper.selectByName(name);
}
}

View File

@@ -10,6 +10,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.adminserver.modules.system.framework.codegen.config.CodegenProperties;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
@@ -119,6 +120,8 @@ public class ToolCodegenEngine {
private void initGlobalBindingMap() {
// 全局配置
globalBindingMap.put("basePackage", codegenProperties.getBasePackage());
globalBindingMap.put("baseFrameworkPackage", StrUtil.subBefore(codegenProperties.getBasePackage(),
'.', true) + '.' + "framework");
// 全局 Java Bean
globalBindingMap.put("CommonResultClassName", CommonResult.class.getName());
globalBindingMap.put("PageResultClassName", PageResult.class.getName());
@@ -134,6 +137,7 @@ public class ToolCodegenEngine {
globalBindingMap.put("ServiceExceptionUtilClassName", ServiceExceptionUtil.class.getName());
globalBindingMap.put("DateUtilsClassName", DateUtils.class.getName());
globalBindingMap.put("ExcelUtilsClassName", ExcelUtils.class.getName());
globalBindingMap.put("ObjectUtilsClassName", ObjectUtils.class.getName());
globalBindingMap.put("DictConvertClassName", DictConvert.class.getName());
globalBindingMap.put("OperateLogClassName", OperateLog.class.getName());
globalBindingMap.put("OperateTypeEnumClassName", OperateTypeEnum.class.getName());
@@ -191,7 +195,7 @@ public class ToolCodegenEngine {
}
private static String javaFilePath(String path) {
return "java/${basePackage}/${table.moduleName}/" + path + ".java";
return "java/${basePackage}/modules/${table.moduleName}/" + path + ".java";
}
private static String vueTemplatePath(String path) {

View File

@@ -16,6 +16,7 @@ import org.apache.commons.collections4.keyvalue.DefaultKeyValue;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import static com.alibaba.druid.sql.SQLUtils.normalize;
@@ -63,10 +64,17 @@ public class ToolCodegenSQLParser {
private static ToolSchemaTableDO parseTable(SQLCreateTableStatement statement) {
return ToolSchemaTableDO.builder()
.tableName(statement.getTableSource().getTableName(true))
.tableComment(((SQLCharExpr) statement.getComment()).getText())
.tableComment(getCommentText(statement))
.build();
}
private static String getCommentText(SQLCreateTableStatement statement) {
if (statement == null || statement.getComment() == null) {
return "";
}
return ((SQLCharExpr) statement.getComment()).getText();
}
private static List<ToolSchemaColumnDO> parseColumns(SQLCreateTableStatement statement) {
List<ToolSchemaColumnDO> columns = new ArrayList<>();
statement.getTableElementList().forEach(element -> parseColumn(columns, element));
@@ -97,7 +105,8 @@ public class ToolCodegenSQLParser {
columns.add(ToolSchemaColumnDO.builder()
.columnName(normalize(definition.getColumnName()))
.columnType(definition.getDataType().toString())
.columnComment(normalize(definition.getComment().toString()))
.columnComment(Objects.isNull(definition.getComment()) ? ""
: normalize(definition.getComment().toString()))
.nullable(!text.contains(" NOT NULL"))
.primaryKey(false)
.autoIncrement(text.contains("AUTO_INCREMENT"))