!577 发布 5.2.2 正式版 安全性提升
Merge pull request !577 from 疯狂的狮子Li/dev
已添加12个文件
已删除6个文件
已修改98个文件
| | |
| | | <configuration default="false" name="ruoyi-monitor-admin" type="docker-deploy" factoryName="dockerfile" server-name="Docker"> |
| | | <deployment type="dockerfile"> |
| | | <settings> |
| | | <option name="imageTag" value="ruoyi/ruoyi-monitor-admin:5.2.1" /> |
| | | <option name="imageTag" value="ruoyi/ruoyi-monitor-admin:5.2.2" /> |
| | | <option name="buildOnly" value="true" /> |
| | | <option name="sourceFilePath" value="ruoyi-extend/ruoyi-monitor-admin/Dockerfile" /> |
| | | </settings> |
| | |
| | | <component name="ProjectRunConfigurationManager"> |
| | | <configuration default="false" name="ruoyi-server" type="docker-deploy" factoryName="dockerfile" server-name="Docker"> |
| | | <configuration default="false" name="ruoyi-server" type="docker-deploy" factoryName="dockerfile" server-name="æ¼ç¤ºæº"> |
| | | <deployment type="dockerfile"> |
| | | <settings> |
| | | <option name="imageTag" value="ruoyi/ruoyi-server:5.2.1" /> |
| | | <option name="imageTag" value="ruoyi/ruoyi-server:5.2.2" /> |
| | | <option name="buildOnly" value="true" /> |
| | | <option name="sourceFilePath" value="ruoyi-admin/Dockerfile" /> |
| | | </settings> |
| | | </deployment> |
| | | <method v="2" /> |
| | | </configuration> |
| | | </component> |
| | | </component> |
| | |
| | | <configuration default="false" name="ruoyi-snailjob-server" type="docker-deploy" factoryName="dockerfile" server-name="Docker"> |
| | | <deployment type="dockerfile"> |
| | | <settings> |
| | | <option name="imageTag" value="ruoyi/ruoyi-snailjob-server:5.2.1" /> |
| | | <option name="imageTag" value="ruoyi/ruoyi-snailjob-server:5.2.2" /> |
| | | <option name="buildOnly" value="true" /> |
| | | <option name="sourceFilePath" value="ruoyi-extend/ruoyi-snailjob-server/Dockerfile" /> |
| | | </settings> |
| | |
| | | [](https://gitee.com/dromara/RuoYi-Vue-Plus/blob/master/LICENSE) |
| | | [](https://www.jetbrains.com/?from=RuoYi-Vue-Plus) |
| | | <br> |
| | | [](https://gitee.com/dromara/RuoYi-Vue-Plus) |
| | | [](https://gitee.com/dromara/RuoYi-Vue-Plus) |
| | | []() |
| | | []() |
| | | []() |
| | |
| | | | æ°æ®åºè¿æ¥æ± | éç¨ HikariCP Spring宿¹å
ç½®è¿æ¥æ± é
ç½®ç®å 以æ§è½ä¸ç¨³å®æ§é»åå¤©ä¸ | éç¨ druid bugä¼å¤ 社åºç»´æ¤å·® æ´»è·åº¦ä½ é
ç½®ä¼å¤ç¹çæ§è½ä¸è¬ | |
| | | | æ°æ®åºä¸»é® | éç¨ éªè±ID åºäºæ¶é´æ³ç æåºå¢é¿ å¯ä¸ID åä¹ä¸ç¨ä¸ºååºå表 æ°æ®å并主é®å²çªéå¤èåæ | éç¨ æ°æ®åºèªå¢ID æ¯ææ°æ®éæé 䏿¯æå¤æ°æ®æºä¸»é®å¯ä¸ | |
| | | | WebSocketåè®® | åºäº Spring å°è£
ç WebSocket åè®® æ©å±äºTokené´æä¸åå¸å¼ä¼è¯åæ¥ ä¸ååªæ¯åºäºåæºçåºç© | æ | |
| | | | SSEæ¨é | éç¨ Spring SSE å®ç° æ©å±äºTokené´æä¸åå¸å¼ä¼è¯åæ¥ | æ | |
| | | | åºåå | éç¨ Jackson Spring宿¹å
ç½®åºåå é è°±!!! | éç¨ fastjson bugjson è¿è¿é»å | |
| | | | åå¸å¼å¹ç | åèç¾å¢GTISé²éç³»ç»ç®åå®ç°(ç»èå¯çææ¡£) | æå¨ç¼å注解åºäºaopå®ç° | |
| | | | åå¸å¼é | éç¨ Lock4j åºå±åºäº Redisson | æ | |
| | |
| | | | æ¥å£ææ¡£ | éç¨ SpringDocãjavadoc æ æ³¨è§£é¶å
¥ä¾µåºäºjava注é<br/>åªéææ³¨éå好 æ éååä¸å¤§å çææ¡£æ³¨è§£äº | éç¨ Springfox å·²åæ¢ç»´æ¤ éè¦ç¼å大éçæ³¨è§£æ¥æ¯æææ¡£çæ | |
| | | | æ ¡éªæ¡æ¶ | éç¨ Validation æ¯ææ³¨è§£ä¸å·¥å
·ç±»æ ¡éª æ³¨è§£æ¯æå½é
å | ä»
æ¯ææ³¨è§£ 䏿³¨è§£ä¸æ¯æå½é
å | |
| | | | Excelæ¡æ¶ | éç¨ Alibaba EasyExcel åºäºæä»¶å<br/>æ¡æ¶å¯¹å
¶å¢å äºå¾å¤åè½ ä¾å¦ èªå¨åå¹¶ç¸åå
容 èªå¨æåå¸å± åå
¸ç¿»è¯ç | åºäº POI æåå®ç° åè½æé 夿 æ©å±æ§å·® | |
| | | | 工使µæ¯æ | æ¯æåç§å¤æå®¡æ¹ 转å å§æ´¾ å åç¾ ä¼ç¾ æç¾ ç¥¨ç¾ çåè½ | æ | |
| | | | å·¥å
·ç±»æ¡æ¶ | éç¨ HutoolãLombok ä¸ç¾ç§å·¥å
·è¦ç90%ç使ç¨éæ± åºäºæ³¨è§£èªå¨çæ get set çç®åæ¡æ¶å¤§é代ç | æåå·¥å
·ç¨³å®æ§å·®æåºé®é¢ å·¥å
·æ°éæé 代ç èè¿éèªå·±æå get set ç | |
| | | | çæ§æ¡æ¶ | éç¨ SpringBoot-Admin åºäºSpringBoot宿¹ actuator æ¢éæºå¶<br/>宿¶çæ§æå¡ç¶æ æ¡æ¶è¿ä¸ºå
¶æ©å±äºå¨çº¿æ¥å¿æ¥ççæ§ | æ | |
| | | | é¾è·¯è¿½è¸ª | éç¨ Apache SkyWalking è¿å¨ä¸ºè¯·æ±ä¸ç¥éå»åªäº å°åªåºäºé®é¢èç¦æ¼å<br/>ç¨äºå®å³å¯å®æ¶æ¥ç请æ±ç»è¿çæ¯ä¸å¤æ¯ä¸ä¸ªèç¹ | æ | |
| | |
| | | <description>RuoYi-Vue-Pluså¤ç§æ·ç®¡çç³»ç»</description> |
| | | |
| | | <properties> |
| | | <revision>5.2.1</revision> |
| | | <spring-boot.version>3.2.6</spring-boot.version> |
| | | <revision>5.2.2</revision> |
| | | <spring-boot.version>3.2.9</spring-boot.version> |
| | | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
| | | <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> |
| | | <java.version>17</java.version> |
| | | <mybatis.version>3.5.16</mybatis.version> |
| | | <springdoc.version>2.5.0</springdoc.version> |
| | | <springdoc.version>2.6.0</springdoc.version> |
| | | <therapi-javadoc.version>0.15.0</therapi-javadoc.version> |
| | | <poi.version>5.2.3</poi.version> |
| | | <easyexcel.version>3.3.4</easyexcel.version> |
| | | <easyexcel.version>4.0.2</easyexcel.version> |
| | | <velocity.version>2.3</velocity.version> |
| | | <satoken.version>1.38.0</satoken.version> |
| | | <mybatis-plus.version>3.5.7</mybatis-plus.version> |
| | | <p6spy.version>3.9.1</p6spy.version> |
| | | <hutool.version>5.8.27</hutool.version> |
| | | <hutool.version>5.8.31</hutool.version> |
| | | <okhttp.version>4.10.0</okhttp.version> |
| | | <spring-boot-admin.version>3.2.3</spring-boot-admin.version> |
| | | <redisson.version>3.31.0</redisson.version> |
| | | <redisson.version>3.34.1</redisson.version> |
| | | <lock4j.version>2.2.7</lock4j.version> |
| | | <dynamic-ds.version>4.3.1</dynamic-ds.version> |
| | | <alibaba-ttl.version>2.14.4</alibaba-ttl.version> |
| | | <snailjob.version>1.0.1</snailjob.version> |
| | | <mapstruct-plus.version>1.3.6</mapstruct-plus.version> |
| | | <snailjob.version>1.1.2</snailjob.version> |
| | | <mapstruct-plus.version>1.4.4</mapstruct-plus.version> |
| | | <mapstruct-plus.lombok.version>0.2.0</mapstruct-plus.lombok.version> |
| | | <lombok.version>1.18.32</lombok.version> |
| | | <lombok.version>1.18.34</lombok.version> |
| | | <bouncycastle.version>1.76</bouncycastle.version> |
| | | <justauth.version>1.16.6</justauth.version> |
| | | <!-- 离线IPå°åå®ä½åº --> |
| | | <ip2region.version>2.7.0</ip2region.version> |
| | | <undertow.version>2.3.15.Final</undertow.version> |
| | | |
| | | <!-- OSS é
ç½® --> |
| | | <aws.sdk.version>2.25.15</aws.sdk.version> |
| | | <aws.crt.version>0.29.13</aws.crt.version> |
| | | <!-- SMS é
ç½® --> |
| | | <sms4j.version>3.2.1</sms4j.version> |
| | | <sms4j.version>3.3.2</sms4j.version> |
| | | <!-- éå¶æ¡æ¶ä¸çfastjsonçæ¬ --> |
| | | <fastjson.version>1.2.83</fastjson.version> |
| | | <!-- é¢åè¿è¡æ¶çD-ORMä¾èµ --> |
| | | <anyline.version>8.7.2-20240808</anyline.version> |
| | | <!--工使µé
ç½®--> |
| | | <flowable.version>7.0.0</flowable.version> |
| | | <flowable.version>7.0.1</flowable.version> |
| | | |
| | | <!-- æä»¶çæ¬ --> |
| | | <maven-jar-plugin.version>3.2.2</maven-jar-plugin.version> |
| | |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.apache.poi</groupId> |
| | | <artifactId>poi</artifactId> |
| | | <version>${poi.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.apache.poi</groupId> |
| | | <artifactId>poi-ooxml</artifactId> |
| | | <version>${poi.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.alibaba</groupId> |
| | | <artifactId>easyexcel</artifactId> |
| | | <version>${easyexcel.version}</version> |
| | | <exclusions> |
| | | <exclusion> |
| | | <groupId>org.apache.poi</groupId> |
| | | <artifactId>poi-ooxml-schemas</artifactId> |
| | | </exclusion> |
| | | </exclusions> |
| | | </dependency> |
| | | |
| | | <!-- velocity代ç çæä½¿ç¨æ¨¡æ¿ --> |
| | |
| | | <version>${snailjob.version}</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.alibaba</groupId> |
| | | <artifactId>transmittable-thread-local</artifactId> |
| | | <version>${alibaba-ttl.version}</version> |
| | | </dependency> |
| | | |
| | | <!-- å å¯å
å¼å
¥ --> |
| | | <dependency> |
| | | <groupId>org.bouncycastle</groupId> |
| | |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>io.undertow</groupId> |
| | | <artifactId>undertow-core</artifactId> |
| | | <version>${undertow.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>io.undertow</groupId> |
| | | <artifactId>undertow-servlet</artifactId> |
| | | <version>${undertow.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>io.undertow</groupId> |
| | | <artifactId>undertow-websockets-jsr</artifactId> |
| | | <version>${undertow.version}</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <artifactId>commons-compress</artifactId> |
| | | <groupId>org.apache.commons</groupId> |
| | | <version>1.26.2</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.alibaba</groupId> |
| | | <artifactId>fastjson</artifactId> |
| | | <version>${fastjson.version}</version> |
| | |
| | | <groupId>com.mysql</groupId> |
| | | <artifactId>mysql-connector-j</artifactId> |
| | | </dependency> |
| | | <!-- Oracle --> |
| | | <dependency> |
| | | <groupId>com.oracle.database.jdbc</groupId> |
| | | <artifactId>ojdbc8</artifactId> |
| | | </dependency> |
| | | <!-- PostgreSql --> |
| | | <dependency> |
| | | <groupId>org.postgresql</groupId> |
| | | <artifactId>postgresql</artifactId> |
| | | </dependency> |
| | | <!-- SqlServer --> |
| | | <dependency> |
| | | <groupId>com.microsoft.sqlserver</groupId> |
| | | <artifactId>mssql-jdbc</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- <!– mpæ¯æçæ°æ®åºåæ¯æ åªéè¦å¢å 对åºçjdbcä¾èµå³å¯ –>--> |
| | | <!-- <!– Oracle –>--> |
| | | <!-- <dependency>--> |
| | | <!-- <groupId>com.oracle.database.jdbc</groupId>--> |
| | | <!-- <artifactId>ojdbc8</artifactId>--> |
| | | <!-- </dependency>--> |
| | | <!-- <!– å
¼å®¹oracleä½çæ¬ –>--> |
| | | <!-- <dependency>--> |
| | | <!-- <groupId>com.oracle.database.nls</groupId>--> |
| | | <!-- <artifactId>orai18n</artifactId>--> |
| | | <!-- </dependency>--> |
| | | <!-- <!– PostgreSql –>--> |
| | | <!-- <dependency>--> |
| | | <!-- <groupId>org.postgresql</groupId>--> |
| | | <!-- <artifactId>postgresql</artifactId>--> |
| | | <!-- </dependency>--> |
| | | <!-- <!– SqlServer –>--> |
| | | <!-- <dependency>--> |
| | | <!-- <groupId>com.microsoft.sqlserver</groupId>--> |
| | | <!-- <artifactId>mssql-jdbc</artifactId>--> |
| | | <!-- </dependency>--> |
| | | |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | |
| | | import org.dromara.common.social.config.properties.SocialLoginConfigProperties; |
| | | import org.dromara.common.social.config.properties.SocialProperties; |
| | | import org.dromara.common.social.utils.SocialUtils; |
| | | import org.dromara.common.sse.dto.SseMessageDto; |
| | | import org.dromara.common.sse.utils.SseMessageUtils; |
| | | import org.dromara.common.tenant.helper.TenantHelper; |
| | | import org.dromara.common.websocket.dto.WebSocketMessageDto; |
| | | import org.dromara.common.websocket.utils.WebSocketUtils; |
| | | import org.dromara.system.domain.bo.SysTenantBo; |
| | | import org.dromara.system.domain.vo.SysClientVo; |
| | | import org.dromara.system.domain.vo.SysTenantVo; |
| | |
| | | |
| | | Long userId = LoginHelper.getUserId(); |
| | | scheduledExecutorService.schedule(() -> { |
| | | WebSocketMessageDto dto = new WebSocketMessageDto(); |
| | | SseMessageDto dto = new SseMessageDto(); |
| | | dto.setMessage("欢è¿ç»å½RuoYi-Vue-Plusåå°ç®¡çç³»ç»"); |
| | | dto.setSessionKeys(List.of(userId)); |
| | | WebSocketUtils.publishMessage(dto); |
| | | }, 3, TimeUnit.SECONDS); |
| | | dto.setUserIds(List.of(userId)); |
| | | SseMessageUtils.publishMessage(dto); |
| | | }, 5, TimeUnit.SECONDS); |
| | | return R.ok(loginVo); |
| | | } |
| | | |
| | |
| | | import cn.dev33.satoken.config.SaTokenConfig; |
| | | import cn.dev33.satoken.listener.SaTokenListener; |
| | | import cn.dev33.satoken.stp.SaLoginModel; |
| | | import cn.dev33.satoken.stp.StpUtil; |
| | | import cn.hutool.core.convert.Convert; |
| | | import cn.hutool.http.useragent.UserAgent; |
| | | import cn.hutool.http.useragent.UserAgentUtil; |
| | | import lombok.RequiredArgsConstructor; |
| | |
| | | */ |
| | | @Override |
| | | public void doLogout(String loginType, Object loginId, String tokenValue) { |
| | | RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); |
| | | String tenantId = Convert.toStr(StpUtil.getExtra(tokenValue, LoginHelper.TENANT_KEY)); |
| | | TenantHelper.dynamic(tenantId, () -> { |
| | | RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); |
| | | }); |
| | | log.info("user doLogout, userId:{}, token:{}", loginId, tokenValue); |
| | | } |
| | | |
| | |
| | | */ |
| | | @Override |
| | | public void doKickout(String loginType, Object loginId, String tokenValue) { |
| | | RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); |
| | | String tenantId = Convert.toStr(StpUtil.getExtra(tokenValue, LoginHelper.TENANT_KEY)); |
| | | TenantHelper.dynamic(tenantId, () -> { |
| | | RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); |
| | | }); |
| | | log.info("user doKickout, userId:{}, token:{}", loginId, tokenValue); |
| | | } |
| | | |
| | |
| | | */ |
| | | @Override |
| | | public void doReplaced(String loginType, Object loginId, String tokenValue) { |
| | | RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); |
| | | String tenantId = Convert.toStr(StpUtil.getExtra(tokenValue, LoginHelper.TENANT_KEY)); |
| | | TenantHelper.dynamic(tenantId, () -> { |
| | | RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); |
| | | }); |
| | | log.info("user doReplaced, userId:{}, token:{}", loginId, tokenValue); |
| | | } |
| | | |
| | |
| | | import cn.dev33.satoken.stp.StpUtil; |
| | | import cn.hutool.core.bean.BeanUtil; |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.lang.Opt; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.baomidou.lock.annotation.Lock4j; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import me.zhyd.oauth.model.AuthUser; |
| | | import org.dromara.common.core.constant.CacheConstants; |
| | | import org.dromara.common.core.constant.Constants; |
| | | import org.dromara.common.core.constant.GlobalConstants; |
| | | import org.dromara.common.core.constant.TenantConstants; |
| | | import org.dromara.common.core.domain.dto.RoleDTO; |
| | | import org.dromara.common.core.domain.model.LoginUser; |
| | |
| | | loginUser.setUserType(user.getUserType()); |
| | | loginUser.setMenuPermission(permissionService.getMenuPermission(user.getUserId())); |
| | | loginUser.setRolePermission(permissionService.getRolePermission(user.getUserId())); |
| | | TenantHelper.dynamic(user.getTenantId(), () -> { |
| | | SysDeptVo dept = null; |
| | | if (ObjectUtil.isNotNull(user.getDeptId())) { |
| | | dept = deptService.selectDeptById(user.getDeptId()); |
| | | } |
| | | loginUser.setDeptName(ObjectUtil.isNull(dept) ? "" : dept.getDeptName()); |
| | | loginUser.setDeptCategory(ObjectUtil.isNull(dept) ? "" : dept.getDeptCategory()); |
| | | List<SysRoleVo> roles = roleService.selectRolesByUserId(user.getUserId()); |
| | | loginUser.setRoles(BeanUtil.copyToList(roles, RoleDTO.class)); |
| | | }); |
| | | if (ObjectUtil.isNotNull(user.getDeptId())) { |
| | | Opt<SysDeptVo> deptOpt = Opt.of(user.getDeptId()).map(deptService::selectDeptById); |
| | | loginUser.setDeptName(deptOpt.map(SysDeptVo::getDeptName).orElse(StringUtils.EMPTY)); |
| | | loginUser.setDeptCategory(deptOpt.map(SysDeptVo::getDeptCategory).orElse(StringUtils.EMPTY)); |
| | | } |
| | | List<SysRoleVo> roles = roleService.selectRolesByUserId(user.getUserId()); |
| | | loginUser.setRoles(BeanUtil.copyToList(roles, RoleDTO.class)); |
| | | return loginUser; |
| | | } |
| | | |
| | |
| | | * ç»å½æ ¡éª |
| | | */ |
| | | public void checkLogin(LoginType loginType, String tenantId, String username, Supplier<Boolean> supplier) { |
| | | String errorKey = GlobalConstants.PWD_ERR_CNT_KEY + username; |
| | | String errorKey = CacheConstants.PWD_ERR_CNT_KEY + username; |
| | | String loginFail = Constants.LOGIN_FAIL; |
| | | |
| | | // è·åç¨æ·ç»å½é误次æ°ï¼é»è®¤ä¸º0 (å¯èªå®ä¹éå¶çç¥ ä¾å¦: key + username + ip) |
| | |
| | | import org.dromara.common.redis.utils.RedisUtils; |
| | | import org.dromara.common.satoken.utils.LoginHelper; |
| | | import org.dromara.common.tenant.helper.TenantHelper; |
| | | import org.dromara.system.domain.SysClient; |
| | | import org.dromara.system.domain.SysUser; |
| | | import org.dromara.system.domain.vo.SysClientVo; |
| | | import org.dromara.system.domain.vo.SysUserVo; |
| | |
| | | String tenantId = loginBody.getTenantId(); |
| | | String email = loginBody.getEmail(); |
| | | String emailCode = loginBody.getEmailCode(); |
| | | |
| | | // éè¿é®ç®±æ¥æ¾ç¨æ· |
| | | SysUserVo user = loadUserByEmail(tenantId, email); |
| | | |
| | | loginService.checkLogin(LoginType.EMAIL, tenantId, user.getUserName(), () -> !validateEmailCode(tenantId, email, emailCode)); |
| | | // æ¤å¤å¯æ ¹æ®ç»å½ç¨æ·çæ°æ®ä¸å èªè¡å建 loginUser 屿§ä¸å¤ç¨ç»§æ¿æ©å±å°±è¡äº |
| | | LoginUser loginUser = loginService.buildLoginUser(user); |
| | | LoginUser loginUser = TenantHelper.dynamic(tenantId, () -> { |
| | | SysUserVo user = loadUserByEmail(email); |
| | | loginService.checkLogin(LoginType.EMAIL, tenantId, user.getUserName(), () -> !validateEmailCode(tenantId, email, emailCode)); |
| | | // æ¤å¤å¯æ ¹æ®ç»å½ç¨æ·çæ°æ®ä¸å èªè¡å建 loginUser 屿§ä¸å¤ç¨ç»§æ¿æ©å±å°±è¡äº |
| | | return loginService.buildLoginUser(user); |
| | | }); |
| | | loginUser.setClientKey(client.getClientKey()); |
| | | loginUser.setDeviceType(client.getDeviceType()); |
| | | SaLoginModel model = new SaLoginModel(); |
| | |
| | | return code.equals(emailCode); |
| | | } |
| | | |
| | | private SysUserVo loadUserByEmail(String tenantId, String email) { |
| | | return TenantHelper.dynamic(tenantId, () -> { |
| | | SysUserVo user = userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getEmail, email)); |
| | | if (ObjectUtil.isNull(user)) { |
| | | log.info("ç»å½ç¨æ·ï¼{} ä¸åå¨.", email); |
| | | throw new UserException("user.not.exists", email); |
| | | } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { |
| | | log.info("ç»å½ç¨æ·ï¼{} 已被åç¨.", email); |
| | | throw new UserException("user.blocked", email); |
| | | } |
| | | return user; |
| | | }); |
| | | private SysUserVo loadUserByEmail(String email) { |
| | | SysUserVo user = userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getEmail, email)); |
| | | if (ObjectUtil.isNull(user)) { |
| | | log.info("ç»å½ç¨æ·ï¼{} ä¸åå¨.", email); |
| | | throw new UserException("user.not.exists", email); |
| | | } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { |
| | | log.info("ç»å½ç¨æ·ï¼{} 已被åç¨.", email); |
| | | throw new UserException("user.blocked", email); |
| | | } |
| | | return user; |
| | | } |
| | | |
| | | } |
| | |
| | | if (captchaEnabled) { |
| | | validateCaptcha(tenantId, username, code, uuid); |
| | | } |
| | | |
| | | SysUserVo user = loadUserByUsername(tenantId, username); |
| | | loginService.checkLogin(LoginType.PASSWORD, tenantId, username, () -> !BCrypt.checkpw(password, user.getPassword())); |
| | | // æ¤å¤å¯æ ¹æ®ç»å½ç¨æ·çæ°æ®ä¸å èªè¡å建 loginUser |
| | | LoginUser loginUser = loginService.buildLoginUser(user); |
| | | LoginUser loginUser = TenantHelper.dynamic(tenantId, () -> { |
| | | SysUserVo user = loadUserByUsername(username); |
| | | loginService.checkLogin(LoginType.PASSWORD, tenantId, username, () -> !BCrypt.checkpw(password, user.getPassword())); |
| | | // æ¤å¤å¯æ ¹æ®ç»å½ç¨æ·çæ°æ®ä¸å èªè¡å建 loginUser |
| | | return loginService.buildLoginUser(user); |
| | | }); |
| | | loginUser.setClientKey(client.getClientKey()); |
| | | loginUser.setDeviceType(client.getDeviceType()); |
| | | SaLoginModel model = new SaLoginModel(); |
| | |
| | | } |
| | | } |
| | | |
| | | private SysUserVo loadUserByUsername(String tenantId, String username) { |
| | | return TenantHelper.dynamic(tenantId, () -> { |
| | | SysUserVo user = userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserName, username)); |
| | | if (ObjectUtil.isNull(user)) { |
| | | log.info("ç»å½ç¨æ·ï¼{} ä¸åå¨.", username); |
| | | throw new UserException("user.not.exists", username); |
| | | } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { |
| | | log.info("ç»å½ç¨æ·ï¼{} 已被åç¨.", username); |
| | | throw new UserException("user.blocked", username); |
| | | } |
| | | return user; |
| | | }); |
| | | private SysUserVo loadUserByUsername(String username) { |
| | | SysUserVo user = userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserName, username)); |
| | | if (ObjectUtil.isNull(user)) { |
| | | log.info("ç»å½ç¨æ·ï¼{} ä¸åå¨.", username); |
| | | throw new UserException("user.not.exists", username); |
| | | } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { |
| | | log.info("ç»å½ç¨æ·ï¼{} 已被åç¨.", username); |
| | | throw new UserException("user.blocked", username); |
| | | } |
| | | return user; |
| | | } |
| | | |
| | | } |
| | |
| | | import org.dromara.common.redis.utils.RedisUtils; |
| | | import org.dromara.common.satoken.utils.LoginHelper; |
| | | import org.dromara.common.tenant.helper.TenantHelper; |
| | | import org.dromara.system.domain.SysClient; |
| | | import org.dromara.system.domain.SysUser; |
| | | import org.dromara.system.domain.vo.SysClientVo; |
| | | import org.dromara.system.domain.vo.SysUserVo; |
| | |
| | | String tenantId = loginBody.getTenantId(); |
| | | String phonenumber = loginBody.getPhonenumber(); |
| | | String smsCode = loginBody.getSmsCode(); |
| | | |
| | | // éè¿ææºå·æ¥æ¾ç¨æ· |
| | | SysUserVo user = loadUserByPhonenumber(tenantId, phonenumber); |
| | | |
| | | loginService.checkLogin(LoginType.SMS, tenantId, user.getUserName(), () -> !validateSmsCode(tenantId, phonenumber, smsCode)); |
| | | // æ¤å¤å¯æ ¹æ®ç»å½ç¨æ·çæ°æ®ä¸å èªè¡å建 loginUser 屿§ä¸å¤ç¨ç»§æ¿æ©å±å°±è¡äº |
| | | LoginUser loginUser = loginService.buildLoginUser(user); |
| | | LoginUser loginUser = TenantHelper.dynamic(tenantId, () -> { |
| | | SysUserVo user = loadUserByPhonenumber(phonenumber); |
| | | loginService.checkLogin(LoginType.SMS, tenantId, user.getUserName(), () -> !validateSmsCode(tenantId, phonenumber, smsCode)); |
| | | // æ¤å¤å¯æ ¹æ®ç»å½ç¨æ·çæ°æ®ä¸å èªè¡å建 loginUser 屿§ä¸å¤ç¨ç»§æ¿æ©å±å°±è¡äº |
| | | return loginService.buildLoginUser(user); |
| | | }); |
| | | loginUser.setClientKey(client.getClientKey()); |
| | | loginUser.setDeviceType(client.getDeviceType()); |
| | | SaLoginModel model = new SaLoginModel(); |
| | |
| | | return code.equals(smsCode); |
| | | } |
| | | |
| | | private SysUserVo loadUserByPhonenumber(String tenantId, String phonenumber) { |
| | | return TenantHelper.dynamic(tenantId, () -> { |
| | | SysUserVo user = userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getPhonenumber, phonenumber)); |
| | | if (ObjectUtil.isNull(user)) { |
| | | log.info("ç»å½ç¨æ·ï¼{} ä¸åå¨.", phonenumber); |
| | | throw new UserException("user.not.exists", phonenumber); |
| | | } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { |
| | | log.info("ç»å½ç¨æ·ï¼{} 已被åç¨.", phonenumber); |
| | | throw new UserException("user.blocked", phonenumber); |
| | | } |
| | | return user; |
| | | }); |
| | | private SysUserVo loadUserByPhonenumber(String phonenumber) { |
| | | SysUserVo user = userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getPhonenumber, phonenumber)); |
| | | if (ObjectUtil.isNull(user)) { |
| | | log.info("ç»å½ç¨æ·ï¼{} ä¸åå¨.", phonenumber); |
| | | throw new UserException("user.not.exists", phonenumber); |
| | | } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { |
| | | log.info("ç»å½ç¨æ·ï¼{} 已被åç¨.", phonenumber); |
| | | throw new UserException("user.blocked", phonenumber); |
| | | } |
| | | return user; |
| | | } |
| | | |
| | | } |
| | |
| | | } else { |
| | | social = list.get(0); |
| | | } |
| | | // æ¥æ¾ç¨æ· |
| | | SysUserVo user = loadUser(social.getTenantId(), social.getUserId()); |
| | | |
| | | // æ¤å¤å¯æ ¹æ®ç»å½ç¨æ·çæ°æ®ä¸å èªè¡å建 loginUser 屿§ä¸å¤ç¨ç»§æ¿æ©å±å°±è¡äº |
| | | LoginUser loginUser = loginService.buildLoginUser(user); |
| | | LoginUser loginUser = TenantHelper.dynamic(social.getTenantId(), () -> { |
| | | SysUserVo user = loadUser(social.getUserId()); |
| | | // æ¤å¤å¯æ ¹æ®ç»å½ç¨æ·çæ°æ®ä¸å èªè¡å建 loginUser 屿§ä¸å¤ç¨ç»§æ¿æ©å±å°±è¡äº |
| | | return loginService.buildLoginUser(user); |
| | | }); |
| | | loginUser.setClientKey(client.getClientKey()); |
| | | loginUser.setDeviceType(client.getDeviceType()); |
| | | SaLoginModel model = new SaLoginModel(); |
| | |
| | | return loginVo; |
| | | } |
| | | |
| | | private SysUserVo loadUser(String tenantId, Long userId) { |
| | | return TenantHelper.dynamic(tenantId, () -> { |
| | | SysUserVo user = userMapper.selectVoById(userId); |
| | | if (ObjectUtil.isNull(user)) { |
| | | log.info("ç»å½ç¨æ·ï¼{} ä¸åå¨.", ""); |
| | | throw new UserException("user.not.exists", ""); |
| | | } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { |
| | | log.info("ç»å½ç¨æ·ï¼{} 已被åç¨.", ""); |
| | | throw new UserException("user.blocked", ""); |
| | | } |
| | | return user; |
| | | }); |
| | | private SysUserVo loadUser(Long userId) { |
| | | SysUserVo user = userMapper.selectVoById(userId); |
| | | if (ObjectUtil.isNull(user)) { |
| | | log.info("ç»å½ç¨æ·ï¼{} ä¸åå¨.", ""); |
| | | throw new UserException("user.not.exists", ""); |
| | | } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { |
| | | log.info("ç»å½ç¨æ·ï¼{} 已被åç¨.", ""); |
| | | throw new UserException("user.blocked", ""); |
| | | } |
| | | return user; |
| | | } |
| | | |
| | | } |
| | |
| | | url: http://localhost:9090/admin |
| | | instance: |
| | | service-host-type: IP |
| | | metadata: |
| | | username: ${spring.boot.admin.client.username} |
| | | userpassword: ${spring.boot.admin.client.password} |
| | | username: ruoyi |
| | | password: 123456 |
| | | |
| | |
| | | url: http://localhost:9090/admin |
| | | instance: |
| | | service-host-type: IP |
| | | metadata: |
| | | username: ${spring.boot.admin.client.username} |
| | | userpassword: ${spring.boot.admin.client.password} |
| | | username: ruoyi |
| | | password: 123456 |
| | | |
| | |
| | | # swagger ææ¡£é
ç½® |
| | | - /*/api-docs |
| | | - /*/api-docs/** |
| | | # actuator çæ§é
ç½® |
| | | - /actuator |
| | | - /actuator/** |
| | | |
| | | # å¤ç§æ·é
ç½® |
| | | tenant: |
| | |
| | | logfile: |
| | | external-file: ./logs/sys-console.log |
| | | |
| | | --- # é»è®¤/æ¨è使ç¨sseæ¨é |
| | | sse: |
| | | enabled: true |
| | | path: /resource/sse |
| | | |
| | | --- # websocket |
| | | websocket: |
| | | # 妿å
³é éè¦åå端å¼å
³ä¸èµ·å
³é |
| | | enabled: true |
| | | enabled: false |
| | | # è·¯å¾ |
| | | path: /resource/websocket |
| | | # è®¾ç½®è®¿é®æºå°å |
| | |
| | | |
| | | --- #flowableé
ç½® |
| | | flowable: |
| | | # å¼å
³ ç¨äºå¯å¨/åç¨å·¥ä½æµ |
| | | enabled: true |
| | | process.enabled: ${flowable.enabled} |
| | | eventregistry.enabled: ${flowable.enabled} |
| | | async-executor-activate: false #å
³é宿¶ä»»å¡JOB |
| | | # å°databaseSchemaUpdate设置为trueãå½Flowableåç°åºä¸æ°æ®åºè¡¨ç»æä¸ä¸è´æ¶ï¼ä¼èªå¨å°æ°æ®åºè¡¨ç»æåçº§è³æ°çæ¬ã |
| | | database-schema-update: true |
| | |
| | | <module>ruoyi-common-encrypt</module> |
| | | <module>ruoyi-common-tenant</module> |
| | | <module>ruoyi-common-websocket</module> |
| | | <module>ruoyi-common-sse</module> |
| | | </modules> |
| | | |
| | | <artifactId>ruoyi-common</artifactId> |
| | |
| | | </description> |
| | | |
| | | <properties> |
| | | <revision>5.2.1</revision> |
| | | <revision>5.2.2</revision> |
| | | </properties> |
| | | |
| | | <dependencyManagement> |
| | |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- SSE模å --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-sse</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | </dependencies> |
| | | </dependencyManagement> |
| | | |
| | |
| | | <artifactId>ip2region</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.alibaba</groupId> |
| | | <artifactId>transmittable-thread-local</artifactId> |
| | | </dependency> |
| | | |
| | | </dependencies> |
| | | |
| | | </project> |
| | |
| | | */ |
| | | String SYS_DICT_KEY = "sys_dict:"; |
| | | |
| | | /** |
| | | * ç»å½è´¦æ·å¯ç éè¯¯æ¬¡æ° redis key |
| | | */ |
| | | String PWD_ERR_CNT_KEY = "pwd_err_cnt:"; |
| | | |
| | | } |
| | |
| | | String RATE_LIMIT_KEY = GLOBAL_REDIS_KEY + "rate_limit:"; |
| | | |
| | | /** |
| | | * ç»å½è´¦æ·å¯ç éè¯¯æ¬¡æ° redis key |
| | | */ |
| | | String PWD_ERR_CNT_KEY = GLOBAL_REDIS_KEY + "pwd_err_cnt:"; |
| | | |
| | | /** |
| | | * 䏿¹è®¤è¯ redis key |
| | | */ |
| | | String SOCIAL_AUTH_CODE_KEY = GLOBAL_REDIS_KEY + "social_auth_codes:"; |
| | |
| | | String DICT_NORMAL = "0"; |
| | | |
| | | /** |
| | | * éç¨å卿 å¿ |
| | | */ |
| | | String DEL_FLAG_NORMAL = "0"; |
| | | |
| | | /** |
| | | * éç¨å 餿 å¿ |
| | | */ |
| | | String DEL_FLAG_REMOVED = "2"; |
| | | |
| | | /** |
| | | * æ¯å¦ä¸ºç³»ç»é»è®¤ï¼æ¯ï¼ |
| | | */ |
| | | String YES = "Y"; |
| | |
| | | * @return ç¨æ·ids |
| | | */ |
| | | List<Long> selectUserIdsByRoleIds(List<Long> roleIds); |
| | | |
| | | /** |
| | | * éè¿è§è²IDæ¥è¯¢ç¨æ· |
| | | * |
| | | * @param roleIds è§è²ids |
| | | * @return ç¨æ· |
| | | */ |
| | | List<UserDTO> selectUsersByRoleIds(List<Long> roleIds); |
| | | |
| | | /** |
| | | * éè¿é¨é¨IDæ¥è¯¢ç¨æ· |
| | | * |
| | | * @param deptIds é¨é¨ids |
| | | * @return ç¨æ· |
| | | */ |
| | | List<UserDTO> selectUsersByDeptIds(List<Long> deptIds); |
| | | } |
| | |
| | | <groupId>com.alibaba</groupId> |
| | | <artifactId>easyexcel</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <artifactId>commons-compress</artifactId> |
| | | <groupId>org.apache.commons</groupId> |
| | | <version>1.26.2</version> |
| | | </dependency> |
| | | </dependencies> |
| | | |
| | | </project> |
| | |
| | | } |
| | | |
| | | if (!cellValue.equals(val)) { |
| | | if ((i - repeatCell.getCurrent() > 1) && isMerge(list, i, field)) { |
| | | if ((i - repeatCell.getCurrent() > 1)) { |
| | | cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex - 1, colNum, colNum)); |
| | | } |
| | | map.put(field, new RepeatCell(val, i)); |
| | |
| | | if (i > repeatCell.getCurrent() && isMerge(list, i, field)) { |
| | | cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex, colNum, colNum)); |
| | | } |
| | | } else if (!isMerge(list, i, field)) { |
| | | if ((i - repeatCell.getCurrent() > 1)) { |
| | | cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex - 1, colNum, colNum)); |
| | | } |
| | | map.put(field, new RepeatCell(val, i)); |
| | | } |
| | | } |
| | | } |
| | |
| | | package org.dromara.common.mail.config; |
| | | |
| | | import cn.hutool.extra.mail.MailAccount; |
| | | import org.dromara.common.mail.config.properties.MailProperties; |
| | | import org.dromara.common.mail.utils.MailAccount; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| | | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| | |
| | | import cn.hutool.core.map.MapUtil; |
| | | import cn.hutool.core.util.CharUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.hutool.extra.mail.JakartaMail; |
| | | import cn.hutool.extra.mail.JakartaUserPassAuthenticator; |
| | | import cn.hutool.extra.mail.MailAccount; |
| | | import jakarta.mail.Authenticator; |
| | | import jakarta.mail.Session; |
| | | import lombok.AccessLevel; |
| | |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | import java.util.Map.Entry; |
| | | |
| | | /** |
| | | * é®ä»¶å·¥å
·ç±» |
| | |
| | | public static Session getSession(MailAccount mailAccount, boolean isSingleton) { |
| | | Authenticator authenticator = null; |
| | | if (mailAccount.isAuth()) { |
| | | authenticator = new UserPassAuthenticator(mailAccount.getUser(), mailAccount.getPass()); |
| | | authenticator = new JakartaUserPassAuthenticator(mailAccount.getUser(), mailAccount.getPass()); |
| | | } |
| | | |
| | | return isSingleton ? Session.getDefaultInstance(mailAccount.getSmtpProps(), authenticator) // |
| | |
| | | */ |
| | | private static String send(MailAccount mailAccount, boolean useGlobalSession, Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, |
| | | Map<String, InputStream> imageMap, boolean isHtml, File... files) { |
| | | final Mail mail = Mail.create(mailAccount).setUseGlobalSession(useGlobalSession); |
| | | final JakartaMail mail = JakartaMail.create(mailAccount).setUseGlobalSession(useGlobalSession); |
| | | |
| | | // å¯éæé人 |
| | | if (CollUtil.isNotEmpty(ccs)) { |
| | |
| | | |
| | | // å¾ç |
| | | if (MapUtil.isNotEmpty(imageMap)) { |
| | | for (Map.Entry<String, InputStream> entry : imageMap.entrySet()) { |
| | | for (Entry<String, InputStream> entry : imageMap.entrySet()) { |
| | | mail.addImage(entry.getKey(), entry.getValue()); |
| | | // å
³éæµ |
| | | IoUtil.close(entry.getValue()); |
| | |
| | | return result; |
| | | } |
| | | // ------------------------------------------------------------------------------------------------------------------------ Private method end |
| | | |
| | | } |
| | |
| | | */ |
| | | String[] value() default "dept_id"; |
| | | |
| | | /** |
| | | * æéæ è¯ç¬¦ ç¨äºéè¿èåæéæ è¯ç¬¦æ¥è·åæ°æ®æé |
| | | * æ¥ææ¤æ è¯ç¬¦çè§è² å°ä¸ä¼æ¼æ¥æ¤è§è²çæ°æ®è¿æ»¤sql |
| | | * |
| | | * @return æéæ è¯ç¬¦ |
| | | */ |
| | | String permission() default ""; |
| | | } |
| | |
| | | */ |
| | | DataColumn[] value(); |
| | | |
| | | /** |
| | | * æéæ¼æ¥æ è¯ç¬¦(ç¨äºæå®è¿æ¥è¯å¥çsql符å·) |
| | | * å¦ä¸å¡« é»è®¤ select ç¨ OR å
¶ä»è¯å¥ç¨ AND |
| | | * å
容 OR æè
AND |
| | | */ |
| | | String joinStr() default ""; |
| | | |
| | | } |
| | |
| | | * å
ç½®æ°æ®ï¼ |
| | | * - {@code user}: å½åç»å½ç¨æ·ä¿¡æ¯ï¼åè {@link LoginUser} |
| | | * å
ç½®æå¡ï¼ |
| | | * - {@code sdss}: ç³»ç»æ°æ®æéæå¡ï¼åè {@link ISysDataScopeService} |
| | | * - {@code sdss}: ç³»ç»æ°æ®æéæå¡ï¼åè ISysDataScopeService |
| | | * å¦éæ©å±æ°æ®ï¼å¯ä»¥éè¿ {@link DataPermissionHelper} è¿è¡æä½ |
| | | * å¦éæ©å±æå¡ï¼å¯ä»¥éè¿ {@link ISysDataScopeService} èªè¡ç¼å |
| | | * å¦éæ©å±æå¡ï¼å¯ä»¥éè¿ ISysDataScopeService èªè¡ç¼å |
| | | * </p> |
| | | * |
| | | * @author Lion Li |
| | |
| | | |
| | | /** |
| | | * èªå®æ°æ®æé |
| | | * ä½¿ç¨ SpEL 表达å¼ï¼`#{#deptName} IN ( #{@sdss.getRoleCustom( #user.roleId )} )` |
| | | * 妿䏿»¡è¶³æ¡ä»¶ï¼å使ç¨é»è®¤ SQL 表达å¼ï¼`1 = 0` |
| | | */ |
| | | CUSTOM("2", " #{#deptName} IN ( #{@sdss.getRoleCustom( #user.roleId )} ) ", " 1 = 0 "), |
| | | |
| | | /** |
| | | * é¨é¨æ°æ®æé |
| | | * ä½¿ç¨ SpEL 表达å¼ï¼`#{#deptName} = #{#user.deptId}` |
| | | * 妿䏿»¡è¶³æ¡ä»¶ï¼å使ç¨é»è®¤ SQL 表达å¼ï¼`1 = 0` |
| | | */ |
| | | DEPT("3", " #{#deptName} = #{#user.deptId} ", " 1 = 0 "), |
| | | |
| | | /** |
| | | * é¨é¨å以䏿°æ®æé |
| | | * ä½¿ç¨ SpEL 表达å¼ï¼`#{#deptName} IN ( #{@sdss.getDeptAndChild( #user.deptId )}` |
| | | * 妿䏿»¡è¶³æ¡ä»¶ï¼å使ç¨é»è®¤ SQL 表达å¼ï¼`1 = 0` |
| | | */ |
| | | DEPT_AND_CHILD("4", " #{#deptName} IN ( #{@sdss.getDeptAndChild( #user.deptId )} )", " 1 = 0 "), |
| | | |
| | | /** |
| | | * ä»
æ¬äººæ°æ®æé |
| | | * ä½¿ç¨ SpEL 表达å¼ï¼`#{#userName} = #{#user.userId}` |
| | | * 妿䏿»¡è¶³æ¡ä»¶ï¼å使ç¨é»è®¤ SQL 表达å¼ï¼`1 = 0` |
| | | */ |
| | | SELF("5", " #{#userName} = #{#user.userId} ", " 1 = 0 "); |
| | | |
| | |
| | | ? baseEntity.getCreateDept() : loginUser.getDeptId()); |
| | | } |
| | | } |
| | | } else { |
| | | Date date = new Date(); |
| | | this.strictInsertFill(metaObject, "createTime", Date.class, date); |
| | | this.strictInsertFill(metaObject, "updateTime", Date.class, date); |
| | | } |
| | | } catch (Exception e) { |
| | | throw new ServiceException("èªå¨æ³¨å
¥å¼å¸¸ => " + e.getMessage(), HttpStatus.HTTP_UNAUTHORIZED); |
| | |
| | | if (ObjectUtil.isNotNull(userId)) { |
| | | baseEntity.setUpdateBy(userId); |
| | | } |
| | | } else { |
| | | this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date()); |
| | | } |
| | | } catch (Exception e) { |
| | | throw new ServiceException("èªå¨æ³¨å
¥å¼å¸¸ => " + e.getMessage(), HttpStatus.HTTP_UNAUTHORIZED); |
| | |
| | | return where; |
| | | } |
| | | // æé æ°æ®è¿æ»¤æ¡ä»¶ç SQL çæ®µ |
| | | String dataFilterSql = buildDataFilter(dataPermission.value(), isSelect); |
| | | String dataFilterSql = buildDataFilter(dataPermission, isSelect); |
| | | if (StringUtils.isBlank(dataFilterSql)) { |
| | | return where; |
| | | } |
| | |
| | | /** |
| | | * æå»ºæ°æ®è¿æ»¤æ¡ä»¶ç SQL è¯å¥ |
| | | * |
| | | * @param dataColumns æ°æ®æé注解ä¸çåä¿¡æ¯ |
| | | * @param isSelect æ å¿å½åæä½æ¯å¦ä¸ºæ¥è¯¢æä½ï¼æ¥è¯¢æä½åæ´æ°æå 餿ä½å¨å¤çè¿æ»¤æ¡ä»¶æ¶ä¼æä¸åçå¤çæ¹å¼ |
| | | * @param dataPermission æ°æ®æé注解 |
| | | * @param isSelect æ å¿å½åæä½æ¯å¦ä¸ºæ¥è¯¢æä½ï¼æ¥è¯¢æä½åæ´æ°æå 餿ä½å¨å¤çè¿æ»¤æ¡ä»¶æ¶ä¼æä¸åçå¤çæ¹å¼ |
| | | * @return æå»ºçæ°æ®è¿æ»¤æ¡ä»¶ç SQL è¯å¥ |
| | | * @throws ServiceException 妿è§è²çæ°æ®èå´å¼å¸¸æè
key ä¸ value çé¿åº¦ä¸å¹é
ï¼åæåº ServiceException å¼å¸¸ |
| | | */ |
| | | private String buildDataFilter(DataColumn[] dataColumns, boolean isSelect) { |
| | | private String buildDataFilter(DataPermission dataPermission, boolean isSelect) { |
| | | // æ´æ°æå é¤éæ»¡è¶³æææ¡ä»¶ |
| | | String joinStr = isSelect ? " OR " : " AND "; |
| | | if (StringUtils.isNotBlank(dataPermission.joinStr())) { |
| | | joinStr = " " + dataPermission.joinStr() + " "; |
| | | } |
| | | LoginUser user = DataPermissionHelper.getVariable("user"); |
| | | StandardEvaluationContext context = new StandardEvaluationContext(); |
| | | context.setBeanResolver(beanResolver); |
| | |
| | | return ""; |
| | | } |
| | | boolean isSuccess = false; |
| | | for (DataColumn dataColumn : dataColumns) { |
| | | for (DataColumn dataColumn : dataPermission.value()) { |
| | | if (dataColumn.key().length != dataColumn.value().length) { |
| | | throw new ServiceException("è§è²æ°æ®èå´å¼å¸¸ => keyä¸valueé¿åº¦ä¸å¹é
"); |
| | | } |
| | |
| | | )) { |
| | | continue; |
| | | } |
| | | // å
å«æéæ è¯ç¬¦ è¿ç´æ¥è·³è¿ |
| | | if (StringUtils.isNotBlank(dataColumn.permission()) && |
| | | CollUtil.contains(user.getMenuPermission(), dataColumn.permission()) |
| | | ) { |
| | | isSuccess = true; |
| | | continue; |
| | | } |
| | | // 设置注解åé key 为表达å¼åé value 为åéå¼ |
| | | for (int i = 0; i < dataColumn.key().length; i++) { |
| | | context.setVariable(dataColumn.key()[i], dataColumn.value()[i]); |
| | |
| | | |
| | | import cn.dev33.satoken.context.SaHolder; |
| | | import cn.dev33.satoken.context.model.SaStorage; |
| | | import cn.hutool.core.collection.CollectionUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.baomidou.mybatisplus.core.plugins.IgnoreStrategy; |
| | | import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper; |
| | | import lombok.AccessLevel; |
| | | import lombok.NoArgsConstructor; |
| | | import org.dromara.common.core.utils.reflect.ReflectUtils; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | import java.util.Stack; |
| | | import java.util.function.Supplier; |
| | | |
| | | /** |
| | |
| | | public class DataPermissionHelper { |
| | | |
| | | private static final String DATA_PERMISSION_KEY = "data:permission"; |
| | | |
| | | private static final ThreadLocal<Stack<Integer>> REENTRANT_IGNORE = ThreadLocal.withInitial(Stack::new); |
| | | |
| | | /** |
| | | * ä»ä¸ä¸æä¸è·åæå®é®çåéå¼ï¼å¹¶å°å
¶è½¬æ¢ä¸ºæå®çç±»å |
| | |
| | | throw new NullPointerException("data permission context type exception"); |
| | | } |
| | | |
| | | private static IgnoreStrategy getIgnoreStrategy() { |
| | | Object ignoreStrategyLocal = ReflectUtils.getStaticFieldValue(ReflectUtils.getField(InterceptorIgnoreHelper.class, "IGNORE_STRATEGY_LOCAL")); |
| | | if (ignoreStrategyLocal instanceof ThreadLocal<?> IGNORE_STRATEGY_LOCAL) { |
| | | if (IGNORE_STRATEGY_LOCAL.get() instanceof IgnoreStrategy ignoreStrategy) { |
| | | return ignoreStrategy; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * å¼å¯å¿½ç¥æ°æ®æé(å¼å¯åéæå¨è°ç¨ {@link #disableIgnore()} å
³é) |
| | | */ |
| | | public static void enableIgnore() { |
| | | InterceptorIgnoreHelper.handle(IgnoreStrategy.builder().dataPermission(true).build()); |
| | | IgnoreStrategy ignoreStrategy = getIgnoreStrategy(); |
| | | if (ObjectUtil.isNull(ignoreStrategy)) { |
| | | InterceptorIgnoreHelper.handle(IgnoreStrategy.builder().dataPermission(true).build()); |
| | | } else { |
| | | ignoreStrategy.setDataPermission(true); |
| | | } |
| | | Stack<Integer> reentrantStack = REENTRANT_IGNORE.get(); |
| | | reentrantStack.push(reentrantStack.size() + 1); |
| | | } |
| | | |
| | | /** |
| | | * å
³éå¿½ç¥æ°æ®æé |
| | | */ |
| | | public static void disableIgnore() { |
| | | InterceptorIgnoreHelper.clearIgnoreStrategy(); |
| | | IgnoreStrategy ignoreStrategy = getIgnoreStrategy(); |
| | | if (ObjectUtil.isNotNull(ignoreStrategy)) { |
| | | boolean noOtherIgnoreStrategy = !Boolean.TRUE.equals(ignoreStrategy.getDynamicTableName()) |
| | | && !Boolean.TRUE.equals(ignoreStrategy.getBlockAttack()) |
| | | && !Boolean.TRUE.equals(ignoreStrategy.getIllegalSql()) |
| | | && !Boolean.TRUE.equals(ignoreStrategy.getTenantLine()) |
| | | && CollectionUtil.isEmpty(ignoreStrategy.getOthers()); |
| | | Stack<Integer> reentrantStack = REENTRANT_IGNORE.get(); |
| | | boolean empty = reentrantStack.isEmpty() || reentrantStack.pop() == 1; |
| | | if (noOtherIgnoreStrategy && empty) { |
| | | InterceptorIgnoreHelper.clearIgnoreStrategy(); |
| | | } else if (empty) { |
| | | ignoreStrategy.setDataPermission(false); |
| | | } |
| | | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å¨å¿½ç¥æ°æ®æé䏿§è¡ |
| | | * <p>ç¦æ¢å¨å¿½ç¥æ°æ®æé䏿§è¡å¿½ç¥æ°æ®æé</p> |
| | | * |
| | | * @param handle å¤çæ§è¡æ¹æ³ |
| | | */ |
| | |
| | | |
| | | /** |
| | | * å¨å¿½ç¥æ°æ®æé䏿§è¡ |
| | | * <p>ç¦æ¢å¨å¿½ç¥æ°æ®æé䏿§è¡å¿½ç¥æ°æ®æé</p> |
| | | * |
| | | * @param handle å¤çæ§è¡æ¹æ³ |
| | | */ |
| | |
| | | |
| | | private String getCombineKey(RateLimiter rateLimiter, JoinPoint point) { |
| | | String key = rateLimiter.key(); |
| | | if (StringUtils.isNotBlank(key)) { |
| | | // 夿 key ä¸ä¸ºç©º å 䏿¯è¡¨è¾¾å¼ |
| | | if (StringUtils.isNotBlank(key) && StringUtils.containsAny(key, "#")) { |
| | | MethodSignature signature = (MethodSignature) point.getSignature(); |
| | | Method targetMethod = signature.getMethod(); |
| | | Object[] args = point.getArgs(); |
| | | //noinspection DataFlowIssue |
| | | MethodBasedEvaluationContext context = |
| | | new MethodBasedEvaluationContext(null, targetMethod, args, pnd); |
| | | context.setBeanResolver(new BeanFactoryResolver(SpringUtils.getBeanFactory())); |
| | |
| | | private static final com.github.benmanes.caffeine.cache.Cache<Object, Object> |
| | | CAFFEINE = SpringUtils.getBean("caffeine"); |
| | | |
| | | private final String name; |
| | | private final Cache cache; |
| | | |
| | | public CaffeineCacheDecorator(Cache cache) { |
| | | public CaffeineCacheDecorator(String name, Cache cache) { |
| | | this.name = name; |
| | | this.cache = cache; |
| | | } |
| | | |
| | | @Override |
| | | public String getName() { |
| | | return cache.getName(); |
| | | return name; |
| | | } |
| | | |
| | | @Override |
| | |
| | | } |
| | | |
| | | public String getUniqueKey(Object key) { |
| | | return cache.getName() + ":" + key; |
| | | return name + ":" + key; |
| | | } |
| | | |
| | | @Override |
| | |
| | | private Cache createMap(String name, CacheConfig config) { |
| | | RMap<Object, Object> map = RedisUtils.getClient().getMap(name); |
| | | |
| | | Cache cache = new CaffeineCacheDecorator(new RedissonCache(map, allowNullValues)); |
| | | Cache cache = new CaffeineCacheDecorator(name, new RedissonCache(map, allowNullValues)); |
| | | if (transactionAware) { |
| | | cache = new TransactionAwareCacheDecorator(cache); |
| | | } |
| | |
| | | private Cache createMapCache(String name, CacheConfig config) { |
| | | RMapCache<Object, Object> map = RedisUtils.getClient().getMapCache(name); |
| | | |
| | | Cache cache = new CaffeineCacheDecorator(new RedissonCache(map, config, allowNullValues)); |
| | | Cache cache = new CaffeineCacheDecorator(name, new RedissonCache(map, config, allowNullValues)); |
| | | if (transactionAware) { |
| | | cache = new TransactionAwareCacheDecorator(cache); |
| | | } |
| | |
| | | package org.dromara.common.security.config; |
| | | |
| | | import cn.dev33.satoken.exception.NotLoginException; |
| | | import cn.dev33.satoken.filter.SaServletFilter; |
| | | import cn.dev33.satoken.httpauth.basic.SaHttpBasicUtil; |
| | | import cn.dev33.satoken.interceptor.SaInterceptor; |
| | | import cn.dev33.satoken.router.SaRouter; |
| | | import cn.dev33.satoken.stp.StpUtil; |
| | | import cn.dev33.satoken.util.SaResult; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.dromara.common.core.constant.HttpStatus; |
| | | import org.dromara.common.core.utils.ServletUtils; |
| | | import org.dromara.common.core.utils.SpringUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | |
| | | import org.dromara.common.security.handler.AllUrlHandler; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; |
| | | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; |
| | | |
| | |
| | | .excludePathPatterns(securityProperties.getExcludes()); |
| | | } |
| | | |
| | | /** |
| | | * 对 actuator å¥åº·æ£æ¥æ¥å£ åè´¦å·å¯ç é´æ |
| | | */ |
| | | @Bean |
| | | public SaServletFilter getSaServletFilter() { |
| | | String username = SpringUtils.getProperty("spring.boot.admin.client.username"); |
| | | String password = SpringUtils.getProperty("spring.boot.admin.client.password"); |
| | | return new SaServletFilter() |
| | | .addInclude("/actuator", "/actuator/**") |
| | | .setAuth(obj -> { |
| | | SaHttpBasicUtil.check(username + ":" + password); |
| | | }) |
| | | .setError(e -> SaResult.error(e.getMessage()).setCode(HttpStatus.UNAUTHORIZED)); |
| | | } |
| | | |
| | | } |
| | |
| | | /** |
| | | * é¶è¡å¡ |
| | | */ |
| | | BANK_CARD(DesensitizedUtil::bankCard); |
| | | BANK_CARD(DesensitizedUtil::bankCard), |
| | | |
| | | /** |
| | | * 䏿å |
| | | */ |
| | | CHINESE_NAME(DesensitizedUtil::chineseName), |
| | | |
| | | /** |
| | | * åºå®çµè¯ |
| | | */ |
| | | FIXED_PHONE(DesensitizedUtil::fixedPhone), |
| | | |
| | | /** |
| | | * ç¨æ·ID |
| | | */ |
| | | USER_ID(s -> String.valueOf(DesensitizedUtil.userId())), |
| | | |
| | | /** |
| | | * å¯ç |
| | | */ |
| | | PASSWORD(DesensitizedUtil::password), |
| | | |
| | | /** |
| | | * ipv4 |
| | | */ |
| | | IPV4(DesensitizedUtil::ipv4), |
| | | |
| | | /** |
| | | * ipv6 |
| | | */ |
| | | IPV6(DesensitizedUtil::ipv6), |
| | | |
| | | /** |
| | | * ä¸å½å¤§é车çï¼å
嫿®é车è¾ãæ°è½æºè½¦è¾ |
| | | */ |
| | | CAR_LICENSE(DesensitizedUtil::carLicense), |
| | | |
| | | /** |
| | | * åªæ¾ç¤ºç¬¬ä¸ä¸ªå符 |
| | | */ |
| | | FIRST_MASK(DesensitizedUtil::firstMask), |
| | | |
| | | /** |
| | | * æ¸
空为null |
| | | */ |
| | | CLEAR(s -> DesensitizedUtil.clear()), |
| | | |
| | | /** |
| | | * æ¸
空为"" |
| | | */ |
| | | CLEAR_TO_NULL(s -> DesensitizedUtil.clearToNull()); |
| | | |
| | | //å¯èªè¡æ·»å å
¶ä»è±æçç¥ |
| | | |
| | |
| | | case "linkedin" -> new AuthLinkedinRequest(builder.build(), STATE_CACHE); |
| | | case "microsoft" -> new AuthMicrosoftRequest(builder.build(), STATE_CACHE); |
| | | case "renren" -> new AuthRenrenRequest(builder.build(), STATE_CACHE); |
| | | case "stack_overflow" -> new AuthStackOverflowRequest(builder.stackOverflowKey("").build(), STATE_CACHE); |
| | | case "stack_overflow" -> new AuthStackOverflowRequest(builder.build(), STATE_CACHE); |
| | | case "huawei" -> new AuthHuaweiRequest(builder.build(), STATE_CACHE); |
| | | case "wechat_enterprise" -> new AuthWeChatEnterpriseQrcodeRequest(builder.agentId("").build(), STATE_CACHE); |
| | | case "wechat_enterprise" -> new AuthWeChatEnterpriseQrcodeRequest(builder.build(), STATE_CACHE); |
| | | case "gitlab" -> new AuthGitlabRequest(builder.build(), STATE_CACHE); |
| | | case "wechat_mp" -> new AuthWeChatMpRequest(builder.build(), STATE_CACHE); |
| | | case "aliyun" -> new AuthAliyunRequest(builder.build(), STATE_CACHE); |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xmlns="http://maven.apache.org/POM/4.0.0" |
| | | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| | | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common</artifactId> |
| | | <version>${revision}</version> |
| | | </parent> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <artifactId>ruoyi-common-sse</artifactId> |
| | | |
| | | <description> |
| | | ruoyi-common-sse 模å |
| | | </description> |
| | | |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-core</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-redis</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-satoken</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-json</artifactId> |
| | | </dependency> |
| | | </dependencies> |
| | | </project> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.sse.config; |
| | | |
| | | import org.dromara.common.sse.controller.SseController; |
| | | import org.dromara.common.sse.core.SseEmitterManager; |
| | | import org.dromara.common.sse.listener.SseTopicListener; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| | | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| | | import org.springframework.context.annotation.Bean; |
| | | |
| | | /** |
| | | * SSE èªå¨è£
é
|
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @AutoConfiguration |
| | | @ConditionalOnProperty(value = "sse.enabled", havingValue = "true") |
| | | @EnableConfigurationProperties(SseProperties.class) |
| | | public class SseAutoConfiguration { |
| | | |
| | | @Bean |
| | | public SseEmitterManager sseEmitterManager() { |
| | | return new SseEmitterManager(); |
| | | } |
| | | |
| | | @Bean |
| | | public SseTopicListener sseTopicListener() { |
| | | return new SseTopicListener(); |
| | | } |
| | | |
| | | @Bean |
| | | public SseController sseController(SseEmitterManager sseEmitterManager) { |
| | | return new SseController(sseEmitterManager); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.sse.config; |
| | | |
| | | import lombok.Data; |
| | | import org.springframework.boot.context.properties.ConfigurationProperties; |
| | | |
| | | /** |
| | | * SSE é
置项 |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Data |
| | | @ConfigurationProperties("sse") |
| | | public class SseProperties { |
| | | |
| | | private Boolean enabled; |
| | | |
| | | /** |
| | | * è·¯å¾ |
| | | */ |
| | | private String path; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.sse.controller; |
| | | |
| | | import cn.dev33.satoken.annotation.SaIgnore; |
| | | import cn.dev33.satoken.stp.StpUtil; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.dromara.common.core.domain.R; |
| | | import org.dromara.common.satoken.utils.LoginHelper; |
| | | import org.dromara.common.sse.core.SseEmitterManager; |
| | | import org.dromara.common.sse.dto.SseMessageDto; |
| | | import org.springframework.beans.factory.DisposableBean; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| | | import org.springframework.http.MediaType; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * SSE æ§å¶å¨ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @RestController |
| | | @ConditionalOnProperty(value = "sse.enabled", havingValue = "true") |
| | | @RequiredArgsConstructor |
| | | public class SseController implements DisposableBean { |
| | | |
| | | private final SseEmitterManager sseEmitterManager; |
| | | |
| | | /** |
| | | * å»ºç« SSE è¿æ¥ |
| | | */ |
| | | @GetMapping(value = "${sse.path}", produces = MediaType.TEXT_EVENT_STREAM_VALUE) |
| | | public SseEmitter connect() { |
| | | String tokenValue = StpUtil.getTokenValue(); |
| | | Long userId = LoginHelper.getUserId(); |
| | | return sseEmitterManager.connect(userId, tokenValue); |
| | | } |
| | | |
| | | /** |
| | | * å
³é SSE è¿æ¥ |
| | | */ |
| | | @SaIgnore |
| | | @GetMapping(value = "${sse.path}/close") |
| | | public R<Void> close() { |
| | | String tokenValue = StpUtil.getTokenValue(); |
| | | Long userId = LoginHelper.getUserId(); |
| | | sseEmitterManager.disconnect(userId, tokenValue); |
| | | return R.ok(); |
| | | } |
| | | |
| | | /** |
| | | * åç¹å®ç¨æ·åéæ¶æ¯ |
| | | * |
| | | * @param userId ç®æ ç¨æ·ç ID |
| | | * @param msg è¦åéçæ¶æ¯å
容 |
| | | */ |
| | | @GetMapping(value = "${sse.path}/send") |
| | | public R<Void> send(Long userId, String msg) { |
| | | SseMessageDto dto = new SseMessageDto(); |
| | | dto.setUserIds(List.of(userId)); |
| | | dto.setMessage(msg); |
| | | sseEmitterManager.publishMessage(dto); |
| | | return R.ok(); |
| | | } |
| | | |
| | | /** |
| | | * åææç¨æ·åéæ¶æ¯ |
| | | * |
| | | * @param msg è¦åéçæ¶æ¯å
容 |
| | | */ |
| | | @GetMapping(value = "${sse.path}/sendAll") |
| | | public R<Void> send(String msg) { |
| | | sseEmitterManager.publishAll(msg); |
| | | return R.ok(); |
| | | } |
| | | |
| | | /** |
| | | * æ¸
çèµæºãæ¤æ¹æ³ç®å䏿§è¡ä»»ä½æä½ï¼ä½é¿å
å æªå®ç°è导è´é误 |
| | | */ |
| | | @Override |
| | | public void destroy() throws Exception { |
| | | // 鿝æ¶ä¸éè¦åä»ä¹ æ¤æ¹æ³é¿å
æ ç¨æä½æ¥é |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.sse.core; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.dromara.common.redis.utils.RedisUtils; |
| | | import org.dromara.common.sse.dto.SseMessageDto; |
| | | import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; |
| | | |
| | | import java.io.IOException; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | import java.util.function.Consumer; |
| | | |
| | | /** |
| | | * 管ç Server-Sent Events (SSE) è¿æ¥ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Slf4j |
| | | public class SseEmitterManager { |
| | | |
| | | /** |
| | | * 订é
çé¢é |
| | | */ |
| | | private final static String SSE_TOPIC = "global:sse"; |
| | | |
| | | private final static Map<Long, Map<String, SseEmitter>> USER_TOKEN_EMITTERS = new ConcurrentHashMap<>(); |
| | | |
| | | /** |
| | | * 建ç«ä¸æå®ç¨æ·ç SSE è¿æ¥ |
| | | * |
| | | * @param userId ç¨æ·çå¯ä¸æ è¯ç¬¦ï¼ç¨äºåºåä¸åç¨æ·çè¿æ¥ |
| | | * @param token ç¨æ·çå¯ä¸ä»¤çï¼ç¨äºè¯å«å
·ä½çè¿æ¥ |
| | | * @return è¿åä¸ä¸ª SseEmitter å®ä¾ï¼å®¢æ·ç«¯å¯ä»¥éè¿è¯¥å®ä¾æ¥æ¶ SSE äºä»¶ |
| | | */ |
| | | public SseEmitter connect(Long userId, String token) { |
| | | // ä» USER_TOKEN_EMITTERS ä¸è·åæå建å½åç¨æ·ç SseEmitter æ å°è¡¨ï¼ConcurrentHashMapï¼ |
| | | // æ¯ä¸ªç¨æ·å¯ä»¥æå¤ä¸ª SSE è¿æ¥ï¼éè¿ token è¿è¡åºå |
| | | Map<String, SseEmitter> emitters = USER_TOKEN_EMITTERS.computeIfAbsent(userId, k -> new ConcurrentHashMap<>()); |
| | | |
| | | // å建ä¸ä¸ªæ°ç SseEmitter å®ä¾ï¼è¶
æ¶æ¶é´è®¾ç½®ä¸º 0 表示æ éå¶ |
| | | SseEmitter emitter = new SseEmitter(0L); |
| | | |
| | | emitters.put(token, emitter); |
| | | |
| | | // å½ emitter 宿ãè¶
æ¶æåçé误æ¶ï¼ä»æ å°è¡¨ä¸ç§»é¤å¯¹åºç token |
| | | emitter.onCompletion(() -> emitters.remove(token)); |
| | | emitter.onTimeout(() -> emitters.remove(token)); |
| | | emitter.onError((e) -> emitters.remove(token)); |
| | | |
| | | try { |
| | | // å客æ·ç«¯åé䏿¡è¿æ¥æåçäºä»¶ |
| | | emitter.send(SseEmitter.event().comment("connected")); |
| | | } catch (IOException e) { |
| | | // 妿åéæ¶æ¯å¤±è´¥ï¼å仿 å°è¡¨ä¸ç§»é¤ emitter |
| | | emitters.remove(token); |
| | | } |
| | | return emitter; |
| | | } |
| | | |
| | | /** |
| | | * æå¼æå®ç¨æ·ç SSE è¿æ¥ |
| | | * |
| | | * @param userId ç¨æ·çå¯ä¸æ è¯ç¬¦ï¼ç¨äºåºåä¸åç¨æ·çè¿æ¥ |
| | | * @param token ç¨æ·çå¯ä¸ä»¤çï¼ç¨äºè¯å«å
·ä½çè¿æ¥ |
| | | */ |
| | | public void disconnect(Long userId, String token) { |
| | | Map<String, SseEmitter> emitters = USER_TOKEN_EMITTERS.get(userId); |
| | | if (emitters != null) { |
| | | try { |
| | | emitters.get(token).send(SseEmitter.event().comment("disconnected")); |
| | | } catch (Exception ignore) { |
| | | } |
| | | emitters.remove(token); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 订é
SSEæ¶æ¯ä¸»é¢ï¼å¹¶æä¾ä¸ä¸ªæ¶è´¹è
彿°æ¥å¤çæ¥æ¶å°çæ¶æ¯ |
| | | * |
| | | * @param consumer å¤çSSEæ¶æ¯çæ¶è´¹è
彿° |
| | | */ |
| | | public void subscribeMessage(Consumer<SseMessageDto> consumer) { |
| | | RedisUtils.subscribe(SSE_TOPIC, SseMessageDto.class, consumer); |
| | | } |
| | | |
| | | /** |
| | | * åæå®çç¨æ·ä¼è¯åéæ¶æ¯ |
| | | * |
| | | * @param userId è¦åéæ¶æ¯çç¨æ·id |
| | | * @param message è¦åéçæ¶æ¯å
容 |
| | | */ |
| | | public void sendMessage(Long userId, String message) { |
| | | Map<String, SseEmitter> emitters = USER_TOKEN_EMITTERS.get(userId); |
| | | if (emitters != null) { |
| | | for (Map.Entry<String, SseEmitter> entry : emitters.entrySet()) { |
| | | try { |
| | | entry.getValue().send(SseEmitter.event() |
| | | .name("message") |
| | | .data(message)); |
| | | } catch (Exception e) { |
| | | emitters.remove(entry.getKey()); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ¬æºå
¨ç¨æ·ä¼è¯åéæ¶æ¯ |
| | | * |
| | | * @param message è¦åéçæ¶æ¯å
容 |
| | | */ |
| | | public void sendMessage(String message) { |
| | | for (Long userId : USER_TOKEN_EMITTERS.keySet()) { |
| | | sendMessage(userId, message); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * åå¸SSE订é
æ¶æ¯ |
| | | * |
| | | * @param sseMessageDto è¦åå¸çSSEæ¶æ¯å¯¹è±¡ |
| | | */ |
| | | public void publishMessage(SseMessageDto sseMessageDto) { |
| | | List<Long> unsentUserIds = new ArrayList<>(); |
| | | // å½åæå¡å
ç¨æ·,ç´æ¥åéæ¶æ¯ |
| | | for (Long userId : sseMessageDto.getUserIds()) { |
| | | if (USER_TOKEN_EMITTERS.containsKey(userId)) { |
| | | sendMessage(userId, sseMessageDto.getMessage()); |
| | | continue; |
| | | } |
| | | unsentUserIds.add(userId); |
| | | } |
| | | // ä¸å¨å½åæå¡å
ç¨æ·,åå¸è®¢é
æ¶æ¯ |
| | | if (CollUtil.isNotEmpty(unsentUserIds)) { |
| | | SseMessageDto broadcastMessage = new SseMessageDto(); |
| | | broadcastMessage.setMessage(sseMessageDto.getMessage()); |
| | | broadcastMessage.setUserIds(unsentUserIds); |
| | | RedisUtils.publish(SSE_TOPIC, broadcastMessage, consumer -> { |
| | | log.info("SSEåé主é¢è®¢é
æ¶æ¯topic:{} session keys:{} message:{}", |
| | | SSE_TOPIC, unsentUserIds, sseMessageDto.getMessage()); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * åææçç¨æ·åå¸è®¢é
çæ¶æ¯(群å) |
| | | * |
| | | * @param message è¦åå¸çæ¶æ¯å
容 |
| | | */ |
| | | public void publishAll(String message) { |
| | | SseMessageDto broadcastMessage = new SseMessageDto(); |
| | | broadcastMessage.setMessage(message); |
| | | RedisUtils.publish(SSE_TOPIC, broadcastMessage, consumer -> { |
| | | log.info("SSEåé主é¢è®¢é
æ¶æ¯topic:{} message:{}", SSE_TOPIC, message); |
| | | }); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.sse.dto; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * æ¶æ¯çdto |
| | | * |
| | | * @author zendwang |
| | | */ |
| | | @Data |
| | | public class SseMessageDto implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * éè¦æ¨éå°çsession key å表 |
| | | */ |
| | | private List<Long> userIds; |
| | | |
| | | /** |
| | | * éè¦åéçæ¶æ¯ |
| | | */ |
| | | private String message; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.sse.listener; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.dromara.common.sse.core.SseEmitterManager; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.boot.ApplicationArguments; |
| | | import org.springframework.boot.ApplicationRunner; |
| | | import org.springframework.core.Ordered; |
| | | |
| | | /** |
| | | * SSE 主é¢è®¢é
çå¬å¨ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Slf4j |
| | | public class SseTopicListener implements ApplicationRunner, Ordered { |
| | | |
| | | @Autowired |
| | | private SseEmitterManager sseEmitterManager; |
| | | |
| | | /** |
| | | * å¨Spring Bootåºç¨ç¨åºå¯å¨æ¶åå§åSSE主é¢è®¢é
çå¬å¨ |
| | | * |
| | | * @param args åºç¨ç¨åºåæ° |
| | | * @throws Exception åå§åè¿ç¨ä¸å¯è½æåºçå¼å¸¸ |
| | | */ |
| | | @Override |
| | | public void run(ApplicationArguments args) throws Exception { |
| | | sseEmitterManager.subscribeMessage((message) -> { |
| | | log.info("SSE主é¢è®¢é
æ¶å°æ¶æ¯session keys={} message={}", message.getUserIds(), message.getMessage()); |
| | | // 妿keyä¸ä¸ºç©ºå°±æç
§keyåæ¶æ¯ å¦æä¸ºç©ºå°±ç¾¤å |
| | | if (CollUtil.isNotEmpty(message.getUserIds())) { |
| | | message.getUserIds().forEach(key -> { |
| | | sseEmitterManager.sendMessage(key, message.getMessage()); |
| | | }); |
| | | } else { |
| | | sseEmitterManager.sendMessage(message.getMessage()); |
| | | } |
| | | }); |
| | | log.info("åå§åSSE主é¢è®¢é
çå¬å¨æå"); |
| | | } |
| | | |
| | | @Override |
| | | public int getOrder() { |
| | | return -1; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.sse.utils; |
| | | |
| | | import lombok.AccessLevel; |
| | | import lombok.NoArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.dromara.common.core.utils.SpringUtils; |
| | | import org.dromara.common.sse.core.SseEmitterManager; |
| | | import org.dromara.common.sse.dto.SseMessageDto; |
| | | |
| | | /** |
| | | * SSEå·¥å
·ç±» |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Slf4j |
| | | @NoArgsConstructor(access = AccessLevel.PRIVATE) |
| | | public class SseMessageUtils { |
| | | |
| | | private final static SseEmitterManager MANAGER = SpringUtils.getBean(SseEmitterManager.class); |
| | | |
| | | /** |
| | | * åæå®çWebSocketä¼è¯åéæ¶æ¯ |
| | | * |
| | | * @param userId è¦åéæ¶æ¯çç¨æ·id |
| | | * @param message è¦åéçæ¶æ¯å
容 |
| | | */ |
| | | public static void sendMessage(Long userId, String message) { |
| | | MANAGER.sendMessage(userId, message); |
| | | } |
| | | |
| | | /** |
| | | * æ¬æºå
¨ç¨æ·ä¼è¯åéæ¶æ¯ |
| | | * |
| | | * @param message è¦åéçæ¶æ¯å
容 |
| | | */ |
| | | public static void sendMessage(String message) { |
| | | MANAGER.sendMessage(message); |
| | | } |
| | | |
| | | /** |
| | | * åå¸SSE订é
æ¶æ¯ |
| | | * |
| | | * @param sseMessageDto è¦åå¸çSSEæ¶æ¯å¯¹è±¡ |
| | | */ |
| | | public static void publishMessage(SseMessageDto sseMessageDto) { |
| | | MANAGER.publishMessage(sseMessageDto); |
| | | } |
| | | |
| | | /** |
| | | * åææçç¨æ·åå¸è®¢é
çæ¶æ¯(群å) |
| | | * |
| | | * @param message è¦åå¸çæ¶æ¯å
容 |
| | | */ |
| | | public static void publishAll(String message) { |
| | | MANAGER.publishAll(message); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | org.dromara.common.sse.config.SseAutoConfiguration |
| | |
| | | package org.dromara.common.tenant.helper; |
| | | |
| | | import cn.dev33.satoken.stp.StpUtil; |
| | | import cn.hutool.core.collection.CollectionUtil; |
| | | import cn.hutool.core.convert.Convert; |
| | | import com.alibaba.ttl.TransmittableThreadLocal; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.baomidou.mybatisplus.core.plugins.IgnoreStrategy; |
| | | import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper; |
| | | import lombok.AccessLevel; |
| | |
| | | import org.dromara.common.core.constant.GlobalConstants; |
| | | import org.dromara.common.core.utils.SpringUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.core.utils.reflect.ReflectUtils; |
| | | import org.dromara.common.redis.utils.RedisUtils; |
| | | import org.dromara.common.satoken.utils.LoginHelper; |
| | | |
| | | import java.util.Stack; |
| | | import java.util.function.Supplier; |
| | | |
| | | /** |
| | |
| | | |
| | | private static final String DYNAMIC_TENANT_KEY = GlobalConstants.GLOBAL_REDIS_KEY + "dynamicTenant"; |
| | | |
| | | private static final ThreadLocal<String> TEMP_DYNAMIC_TENANT = new TransmittableThreadLocal<>(); |
| | | private static final ThreadLocal<String> TEMP_DYNAMIC_TENANT = new ThreadLocal<>(); |
| | | |
| | | private static final ThreadLocal<Stack<Integer>> REENTRANT_IGNORE = ThreadLocal.withInitial(Stack::new); |
| | | |
| | | /** |
| | | * ç§æ·åè½æ¯å¦å¯ç¨ |
| | |
| | | return Convert.toBool(SpringUtils.getProperty("tenant.enable"), false); |
| | | } |
| | | |
| | | private static IgnoreStrategy getIgnoreStrategy() { |
| | | Object ignoreStrategyLocal = ReflectUtils.getStaticFieldValue(ReflectUtils.getField(InterceptorIgnoreHelper.class, "IGNORE_STRATEGY_LOCAL")); |
| | | if (ignoreStrategyLocal instanceof ThreadLocal<?> IGNORE_STRATEGY_LOCAL) { |
| | | if (IGNORE_STRATEGY_LOCAL.get() instanceof IgnoreStrategy ignoreStrategy) { |
| | | return ignoreStrategy; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * å¼å¯å¿½ç¥ç§æ·(å¼å¯åéæå¨è°ç¨ {@link #disableIgnore()} å
³é) |
| | | */ |
| | | public static void enableIgnore() { |
| | | InterceptorIgnoreHelper.handle(IgnoreStrategy.builder().tenantLine(true).build()); |
| | | IgnoreStrategy ignoreStrategy = getIgnoreStrategy(); |
| | | if (ObjectUtil.isNull(ignoreStrategy)) { |
| | | InterceptorIgnoreHelper.handle(IgnoreStrategy.builder().tenantLine(true).build()); |
| | | } else { |
| | | ignoreStrategy.setTenantLine(true); |
| | | } |
| | | Stack<Integer> reentrantStack = REENTRANT_IGNORE.get(); |
| | | reentrantStack.push(reentrantStack.size() + 1); |
| | | } |
| | | |
| | | /** |
| | | * å
³é忽ç¥ç§æ· |
| | | */ |
| | | public static void disableIgnore() { |
| | | InterceptorIgnoreHelper.clearIgnoreStrategy(); |
| | | IgnoreStrategy ignoreStrategy = getIgnoreStrategy(); |
| | | if (ObjectUtil.isNotNull(ignoreStrategy)) { |
| | | boolean noOtherIgnoreStrategy = !Boolean.TRUE.equals(ignoreStrategy.getDynamicTableName()) |
| | | && !Boolean.TRUE.equals(ignoreStrategy.getBlockAttack()) |
| | | && !Boolean.TRUE.equals(ignoreStrategy.getIllegalSql()) |
| | | && !Boolean.TRUE.equals(ignoreStrategy.getDataPermission()) |
| | | && CollectionUtil.isEmpty(ignoreStrategy.getOthers()); |
| | | Stack<Integer> reentrantStack = REENTRANT_IGNORE.get(); |
| | | boolean empty = reentrantStack.isEmpty() || reentrantStack.pop() == 1; |
| | | if (noOtherIgnoreStrategy && empty) { |
| | | InterceptorIgnoreHelper.clearIgnoreStrategy(); |
| | | } else if (empty) { |
| | | ignoreStrategy.setTenantLine(false); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | package org.dromara.common.tenant.manager; |
| | | |
| | | import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.dromara.common.core.constant.GlobalConstants; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.redis.manager.PlusSpringCacheManager; |
| | |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Slf4j |
| | | public class TenantSpringCacheManager extends PlusSpringCacheManager { |
| | | |
| | | public TenantSpringCacheManager() { |
| | |
| | | |
| | | @Override |
| | | public Cache getCache(String name) { |
| | | if (InterceptorIgnoreHelper.willIgnoreTenantLine("")) { |
| | | return super.getCache(name); |
| | | } |
| | | if (StringUtils.contains(name, GlobalConstants.GLOBAL_REDIS_KEY)) { |
| | | return super.getCache(name); |
| | | } |
| | | String tenantId = TenantHelper.getTenantId(); |
| | | if (StringUtils.isBlank(tenantId)) { |
| | | log.error("æ æ³è·åææçç§æ·id -> Null"); |
| | | } |
| | | if (StringUtils.startsWith(name, tenantId)) { |
| | | // 妿åå¨åç´æ¥è¿å |
| | | return super.getCache(name); |
| | |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>io.undertow</groupId> |
| | | <artifactId>undertow-core</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>io.undertow</groupId> |
| | | <artifactId>undertow-servlet</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>io.undertow</groupId> |
| | | <artifactId>undertow-websockets-jsr</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-actuator</artifactId> |
| | | </dependency> |
| | |
| | | import org.springframework.web.bind.MethodArgumentNotValidException; |
| | | import org.springframework.web.bind.MissingPathVariableException; |
| | | import org.springframework.web.bind.annotation.ExceptionHandler; |
| | | import org.springframework.web.bind.annotation.ResponseStatus; |
| | | import org.springframework.web.bind.annotation.RestControllerAdvice; |
| | | import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; |
| | | import org.springframework.web.servlet.NoHandlerFoundException; |
| | | |
| | | import java.io.IOException; |
| | | |
| | | /** |
| | | * å
¨å±å¼å¸¸å¤çå¨ |
| | |
| | | /** |
| | | * æ¦æªæªç¥çè¿è¡æ¶å¼å¸¸ |
| | | */ |
| | | @ResponseStatus(org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR) |
| | | @ExceptionHandler(IOException.class) |
| | | public void handleRuntimeException(IOException e, HttpServletRequest request) { |
| | | String requestURI = request.getRequestURI(); |
| | | if (requestURI.contains("sse")) { |
| | | // sse ç»å¸¸æ§è¿æ¥ä¸æ ä¾å¦å
³éæµè§å¨ ç´æ¥å±è½ |
| | | return; |
| | | } |
| | | log.error("请æ±å°å'{}',è¿æ¥ä¸æ", requestURI, e); |
| | | } |
| | | |
| | | /** |
| | | * æ¦æªæªç¥çè¿è¡æ¶å¼å¸¸ |
| | | */ |
| | | @ExceptionHandler(RuntimeException.class) |
| | | public R<Void> handleRuntimeException(RuntimeException e, HttpServletRequest request) { |
| | | String requestURI = request.getRequestURI(); |
| | |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.lang3.time.StopWatch; |
| | | import org.dromara.common.core.utils.SpringUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.json.utils.JsonUtils; |
| | | import org.dromara.common.web.filter.RepeatedlyRequestWrapper; |
| | |
| | | |
| | | /** |
| | | * webçè°ç¨æ¶é´ç»è®¡æ¦æªå¨ |
| | | * devç¯å¢ææ |
| | | * |
| | | * @author Lion Li |
| | | * @since 3.3.0 |
| | |
| | | @Slf4j |
| | | public class PlusWebInvokeTimeInterceptor implements HandlerInterceptor { |
| | | |
| | | private final String prodProfile = "prod"; |
| | | |
| | | private final static ThreadLocal<StopWatch> KEY_CACHE = new ThreadLocal<>(); |
| | | |
| | | @Override |
| | | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { |
| | | if (!prodProfile.equals(SpringUtils.getActiveProfile())) { |
| | | String url = request.getMethod() + " " + request.getRequestURI(); |
| | | String url = request.getMethod() + " " + request.getRequestURI(); |
| | | |
| | | // æå°è¯·æ±åæ° |
| | | if (isJsonRequest(request)) { |
| | | String jsonParam = ""; |
| | | if (request instanceof RepeatedlyRequestWrapper) { |
| | | BufferedReader reader = request.getReader(); |
| | | jsonParam = IoUtil.read(reader); |
| | | } |
| | | log.info("[PLUS]å¼å§è¯·æ± => URL[{}],åæ°ç±»å[json],åæ°:[{}]", url, jsonParam); |
| | | } else { |
| | | Map<String, String[]> parameterMap = request.getParameterMap(); |
| | | if (MapUtil.isNotEmpty(parameterMap)) { |
| | | String parameters = JsonUtils.toJsonString(parameterMap); |
| | | log.info("[PLUS]å¼å§è¯·æ± => URL[{}],åæ°ç±»å[param],åæ°:[{}]", url, parameters); |
| | | } else { |
| | | log.info("[PLUS]å¼å§è¯·æ± => URL[{}],æ åæ°", url); |
| | | } |
| | | // æå°è¯·æ±åæ° |
| | | if (isJsonRequest(request)) { |
| | | String jsonParam = ""; |
| | | if (request instanceof RepeatedlyRequestWrapper) { |
| | | BufferedReader reader = request.getReader(); |
| | | jsonParam = IoUtil.read(reader); |
| | | } |
| | | |
| | | StopWatch stopWatch = new StopWatch(); |
| | | KEY_CACHE.set(stopWatch); |
| | | stopWatch.start(); |
| | | log.info("[PLUS]å¼å§è¯·æ± => URL[{}],åæ°ç±»å[json],åæ°:[{}]", url, jsonParam); |
| | | } else { |
| | | Map<String, String[]> parameterMap = request.getParameterMap(); |
| | | if (MapUtil.isNotEmpty(parameterMap)) { |
| | | String parameters = JsonUtils.toJsonString(parameterMap); |
| | | log.info("[PLUS]å¼å§è¯·æ± => URL[{}],åæ°ç±»å[param],åæ°:[{}]", url, parameters); |
| | | } else { |
| | | log.info("[PLUS]å¼å§è¯·æ± => URL[{}],æ åæ°", url); |
| | | } |
| | | } |
| | | |
| | | StopWatch stopWatch = new StopWatch(); |
| | | KEY_CACHE.set(stopWatch); |
| | | stopWatch.start(); |
| | | |
| | | return true; |
| | | } |
| | | |
| | |
| | | |
| | | @Override |
| | | public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { |
| | | if (!prodProfile.equals(SpringUtils.getActiveProfile())) { |
| | | StopWatch stopWatch = KEY_CACHE.get(); |
| | | stopWatch.stop(); |
| | | log.info("[PLUS]ç»æè¯·æ± => URL[{}],èæ¶:[{}]毫ç§", request.getMethod() + " " + request.getRequestURI(), stopWatch.getTime()); |
| | | KEY_CACHE.remove(); |
| | | } |
| | | StopWatch stopWatch = KEY_CACHE.get(); |
| | | stopWatch.stop(); |
| | | log.info("[PLUS]ç»æè¯·æ± => URL[{}],èæ¶:[{}]毫ç§", request.getMethod() + " " + request.getRequestURI(), stopWatch.getTime()); |
| | | KEY_CACHE.remove(); |
| | | } |
| | | |
| | | /** |
| | |
| | | * @param session WebSocketä¼è¯ |
| | | * @param message è¦åéçWebSocketæ¶æ¯å¯¹è±¡ |
| | | */ |
| | | private static void sendMessage(WebSocketSession session, WebSocketMessage<?> message) { |
| | | private synchronized static void sendMessage(WebSocketSession session, WebSocketMessage<?> message) { |
| | | if (session == null || !session.isOpen()) { |
| | | log.warn("[send] sessionä¼è¯å·²ç»å
³é"); |
| | | } else { |
| | |
| | | <artifactId>ruoyi-monitor-admin</artifactId> |
| | | |
| | | <dependencies> |
| | | <!-- SpringWeb模å --> |
| | | <!-- SpringBoot Webå®¹å¨ --> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-web</artifactId> |
| | | <exclusions> |
| | | <exclusion> |
| | | <artifactId>spring-boot-starter-tomcat</artifactId> |
| | | <groupId>org.springframework.boot</groupId> |
| | | </exclusion> |
| | | </exclusions> |
| | | </dependency> |
| | | <!-- web 容å¨ä½¿ç¨ undertow æ§è½æ´å¼º --> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-undertow</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- spring security å®å
¨è®¤è¯ --> |
| | |
| | | .authorizeHttpRequests((authorize) -> |
| | | authorize.requestMatchers( |
| | | new AntPathRequestMatcher(adminContextPath + "/assets/**"), |
| | | new AntPathRequestMatcher(adminContextPath + "/login"), |
| | | new AntPathRequestMatcher("/actuator"), |
| | | new AntPathRequestMatcher("/actuator/**") |
| | | new AntPathRequestMatcher(adminContextPath + "/login") |
| | | ).permitAll() |
| | | .anyRequest().authenticated()) |
| | | .formLogin((formLogin) -> |
| | |
| | | import org.springframework.stereotype.Component; |
| | | import reactor.core.publisher.Mono; |
| | | |
| | | import static de.codecentric.boot.admin.server.domain.values.StatusInfo.*; |
| | | |
| | | /** |
| | | * èªå®ä¹äºä»¶éç¥å¤ç |
| | | * |
| | |
| | | return Mono.fromRunnable(() -> { |
| | | // å®ä¾ç¶ææ¹åäºä»¶ |
| | | if (event instanceof InstanceStatusChangedEvent) { |
| | | // è·åå®ä¾æ³¨ååç§° |
| | | String registName = instance.getRegistration().getName(); |
| | | // è·åå®ä¾ID |
| | | String instanceId = event.getInstance().getValue(); |
| | | // è·åå®ä¾ç¶æ |
| | | String status = ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus(); |
| | | log.info("Instance Status Change: [{}],[{}],[{}]", registName, instanceId, status); |
| | | // è·åæå¡URL |
| | | String serviceUrl = instance.getRegistration().getServiceUrl(); |
| | | String statusName = switch (status) { |
| | | case STATUS_UP -> "æå¡ä¸çº¿"; // å®ä¾æåå¯å¨å¹¶å¯ä»¥æ£å¸¸å¤çè¯·æ± |
| | | case STATUS_OFFLINE -> "æå¡ç¦»çº¿"; //å®ä¾è¢«æå¨æèªå¨å°ä»æå¡ä¸ç§»é¤ |
| | | case STATUS_RESTRICTED -> "æå¡åé"; //表示å®ä¾å¨æäºæ¹é¢åéï¼å¯è½æ æ³å®å
¨æä¾æææå¡ |
| | | case STATUS_OUT_OF_SERVICE -> "忢æå¡ç¶æ"; //表示å®ä¾å·²è¢«æ è®°ä¸ºåæ¢æä¾æå¡ï¼å¯è½æ¯è®¡åå
ç»´æ¤ææµè¯ |
| | | case STATUS_DOWN -> "æå¡ä¸çº¿"; //å®ä¾å å´©æºãé误æå
¶ä»åå 忢è¿è¡ |
| | | case STATUS_UNKNOWN -> "æå¡æªç¥å¼å¸¸"; //çæ§ç³»ç»æ æ³ç¡®å®å®ä¾çå½åç¶æ |
| | | default -> "æªç¥ç¶æ"; //没æå¹é
çç¶æ |
| | | }; |
| | | log.info("Instance Status Change: ç¶æåç§°ã{}ã, 注ååç§°ã{}ã, å®ä¾IDã{}ã, ç¶æã{}ã, æå¡URLã{}ã", |
| | | statusName, registName, instanceId, status, serviceUrl); |
| | | } |
| | | |
| | | }); |
| | | } |
| | | |
| | | } |
| | |
| | | url: http://localhost:9090/admin |
| | | instance: |
| | | service-host-type: IP |
| | | metadata: |
| | | username: ${spring.boot.admin.client.username} |
| | | userpassword: ${spring.boot.admin.client.password} |
| | | username: ruoyi |
| | | password: 123456 |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.aizuda.snailjob.server.starter.filter; |
| | | |
| | | import jakarta.servlet.*; |
| | | import jakarta.servlet.http.HttpServletRequest; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | |
| | | import java.io.IOException; |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.util.Base64; |
| | | |
| | | public class ActuatorAuthFilter implements Filter { |
| | | |
| | | private final String username; |
| | | private final String password; |
| | | |
| | | public ActuatorAuthFilter(String username, String password) { |
| | | this.username = username; |
| | | this.password = password; |
| | | } |
| | | |
| | | @Override |
| | | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { |
| | | HttpServletRequest request = (HttpServletRequest) servletRequest; |
| | | HttpServletResponse response = (HttpServletResponse) servletResponse; |
| | | |
| | | // è·å Authorization 头 |
| | | String authHeader = request.getHeader("Authorization"); |
| | | |
| | | if (authHeader == null || !authHeader.startsWith("Basic ")) { |
| | | // å¦ææ²¡ææä¾ Authorization æè
æ ¼å¼ä¸å¯¹ï¼åè¿å 401 |
| | | response.setHeader("WWW-Authenticate", "Basic realm=\"realm\""); |
| | | response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); |
| | | return; |
| | | } |
| | | |
| | | // è§£ç Base64 ç¼ç çç¨æ·ååå¯ç |
| | | String base64Credentials = authHeader.substring("Basic ".length()); |
| | | byte[] credDecoded = Base64.getDecoder().decode(base64Credentials); |
| | | String credentials = new String(credDecoded, StandardCharsets.UTF_8); |
| | | String[] split = credentials.split(":"); |
| | | if (split.length != 2) { |
| | | response.setHeader("WWW-Authenticate", "Basic realm=\"realm\""); |
| | | response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); |
| | | return; |
| | | } |
| | | // éªè¯ç¨æ·ååå¯ç |
| | | if (!username.equals(split[0]) && password.equals(split[1])) { |
| | | response.setHeader("WWW-Authenticate", "Basic realm=\"realm\""); |
| | | response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); |
| | | return; |
| | | } |
| | | // å¦æè®¤è¯æåï¼ç»§ç»å¤çè¯·æ± |
| | | filterChain.doFilter(request, response); |
| | | } |
| | | |
| | | @Override |
| | | public void init(FilterConfig filterConfig) { |
| | | } |
| | | |
| | | @Override |
| | | public void destroy() { |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.aizuda.snailjob.server.starter.filter; |
| | | |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.boot.web.servlet.FilterRegistrationBean; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.Configuration; |
| | | |
| | | /** |
| | | * æéå®å
¨é
ç½® |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Configuration |
| | | public class SecurityConfig { |
| | | |
| | | @Value("${spring.boot.admin.client.username}") |
| | | private String username; |
| | | @Value("${spring.boot.admin.client.password}") |
| | | private String password; |
| | | |
| | | @Bean |
| | | public FilterRegistrationBean<ActuatorAuthFilter> actuatorFilterRegistrationBean() { |
| | | FilterRegistrationBean<ActuatorAuthFilter> registrationBean = new FilterRegistrationBean<>(); |
| | | registrationBean.setFilter(new ActuatorAuthFilter(username, password)); |
| | | registrationBean.addUrlPatterns("/actuator", "/actuator/**"); |
| | | return registrationBean; |
| | | } |
| | | |
| | | } |
| | |
| | | url: http://localhost:9090/admin |
| | | instance: |
| | | service-host-type: IP |
| | | metadata: |
| | | username: ${spring.boot.admin.client.username} |
| | | userpassword: ${spring.boot.admin.client.password} |
| | | username: ruoyi |
| | | password: 123456 |
| | |
| | | url: http://localhost:9090/admin |
| | | instance: |
| | | service-host-type: IP |
| | | metadata: |
| | | username: ${spring.boot.admin.client.username} |
| | | userpassword: ${spring.boot.admin.client.password} |
| | | username: ruoyi |
| | | password: 123456 |
| | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.core.toolkit.Constants; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import org.apache.poi.ss.formula.functions.T; |
| | | import org.apache.ibatis.annotations.Param; |
| | | import org.dromara.common.mybatis.annotation.DataColumn; |
| | | import org.dromara.common.mybatis.annotation.DataPermission; |
| | | import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; |
| | | import org.dromara.demo.domain.TestDemo; |
| | | import org.dromara.demo.domain.vo.TestDemoVo; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | |
| | |
| | | List<TestDemo> selectList(@Param(Constants.WRAPPER) Wrapper<TestDemo> queryWrapper); |
| | | |
| | | @Override |
| | | @DataPermission({ |
| | | @DataPermission(value = { |
| | | @DataColumn(key = "deptName", value = "dept_id"), |
| | | @DataColumn(key = "userName", value = "user_id") |
| | | }) |
| | | int updateById(@Param(Constants.ENTITY) TestDemo entity); |
| | | }, joinStr = "AND") |
| | | List<TestDemo> selectBatchIds(@Param(Constants.COLL) Collection<? extends Serializable> idList); |
| | | |
| | | @Override |
| | | @DataPermission({ |
| | | @DataColumn(key = "deptName", value = "dept_id"), |
| | | @DataColumn(key = "userName", value = "user_id") |
| | | }) |
| | | int deleteByIds(@Param(Constants.COLL) Collection<?> idList); |
| | | int updateById(@Param(Constants.ENTITY) TestDemo entity); |
| | | |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.dromara.common.core.exception.ServiceException; |
| | | import org.dromara.common.core.utils.MapstructUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.mybatis.core.page.PageQuery; |
| | |
| | | import org.dromara.demo.domain.vo.TestDemoVo; |
| | | import org.dromara.demo.mapper.TestDemoMapper; |
| | | import org.dromara.demo.service.ITestDemoService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.Collection; |
| | |
| | | @Override |
| | | public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) { |
| | | if (isValid) { |
| | | //TODO åä¸äºä¸å¡ä¸çæ ¡éª,夿æ¯å¦éè¦æ ¡éª |
| | | // åä¸äºä¸å¡ä¸çæ ¡éª,夿æ¯å¦éè¦æ ¡éª |
| | | List<TestDemo> list = baseMapper.selectBatchIds(ids); |
| | | if (list.size() != ids.size()) { |
| | | throw new ServiceException("æ¨æ²¡æå 餿é!"); |
| | | } |
| | | } |
| | | return baseMapper.deleteByIds(ids) > 0; |
| | | } |
| | |
| | | <groupId>org.apache.velocity</groupId> |
| | | <artifactId>velocity-engine-core</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.anyline</groupId> |
| | | <artifactId>anyline-environment-spring-data-jdbc</artifactId> |
| | | <version>${anyline.version}</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.anyline</groupId> |
| | | <artifactId>anyline-data-jdbc-mysql</artifactId> |
| | | <version>${anyline.version}</version> |
| | | </dependency> |
| | | |
| | | <!-- anylineæ¯æ100+ç§ç±»åæ°æ®åº æ·»å 对åºçjdbcä¾èµä¸anylineå¯¹åºæ°æ®åºä¾èµå
å³å¯ --> |
| | | <!-- <dependency>--> |
| | | <!-- <groupId>org.anyline</groupId>--> |
| | | <!-- <artifactId>anyline-data-jdbc-oracle</artifactId>--> |
| | | <!-- <version>${anyline.version}</version>--> |
| | | <!-- </dependency>--> |
| | | |
| | | <!-- <dependency>--> |
| | | <!-- <groupId>org.anyline</groupId>--> |
| | | <!-- <artifactId>anyline-data-jdbc-postgresql</artifactId>--> |
| | | <!-- <version>${anyline.version}</version>--> |
| | | <!-- </dependency>--> |
| | | |
| | | <!-- <dependency>--> |
| | | <!-- <groupId>org.anyline</groupId>--> |
| | | <!-- <artifactId>anyline-data-jdbc-mssql</artifactId>--> |
| | | <!-- <version>${anyline.version}</version>--> |
| | | <!-- </dependency>--> |
| | | |
| | | </dependencies> |
| | | |
| | | </project> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.generator.config; |
| | | |
| | | import com.baomidou.dynamic.datasource.DynamicRoutingDataSource; |
| | | import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.anyline.data.datasource.DataSourceMonitor; |
| | | import org.anyline.data.runtime.DataRuntime; |
| | | import org.anyline.util.ConfigTable; |
| | | import org.springframework.jdbc.core.JdbcTemplate; |
| | | import org.springframework.jdbc.datasource.DataSourceUtils; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import javax.sql.DataSource; |
| | | import java.sql.Connection; |
| | | import java.sql.DatabaseMetaData; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * anyline éé
å¨ææ°æ®æºæ¹é |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Slf4j |
| | | @Component |
| | | public class MyBatisDataSourceMonitor implements DataSourceMonitor { |
| | | |
| | | public MyBatisDataSourceMonitor() { |
| | | // è°æ´æ§è¡æ¨¡å¼ä¸ºèªå®ä¹ |
| | | ConfigTable.KEEP_ADAPTER = 2; |
| | | // ç¦ç¨ç¼å |
| | | ConfigTable.METADATA_CACHE_SCOPE = 0; |
| | | } |
| | | |
| | | private final Map<String, String> features = new HashMap<>(); |
| | | |
| | | /** |
| | | * æ°æ®æºç¹å¾ ç¨æ¥å®å adapter å
嫿°æ®åºæJDBCåè®®å
³é®å<br/> |
| | | * ä¸è¬ä¼éè¿ äº§åå_url åæ å¦æè¿ånull ä¸å±æ¹æ³ä¼éè¿driver_产åå_urlåæ |
| | | * |
| | | * @param datasource æ°æ®æº |
| | | * @return String è¿ånullç±ä¸å±èªå¨æå |
| | | */ |
| | | @Override |
| | | public String feature(DataRuntime runtime, Object datasource) { |
| | | String feature = null; |
| | | if (datasource instanceof JdbcTemplate jdbc) { |
| | | DataSource ds = jdbc.getDataSource(); |
| | | if (ds instanceof DynamicRoutingDataSource) { |
| | | String key = DynamicDataSourceContextHolder.peek(); |
| | | feature = features.get(key); |
| | | if (null == feature) { |
| | | Connection con = null; |
| | | try { |
| | | con = DataSourceUtils.getConnection(ds); |
| | | DatabaseMetaData meta = con.getMetaData(); |
| | | String url = meta.getURL(); |
| | | feature = meta.getDatabaseProductName().toLowerCase().replace(" ", "") + "_" + url; |
| | | features.put(key, feature); |
| | | } catch (Exception e) { |
| | | log.error(e.getMessage(), e); |
| | | } finally { |
| | | if (null != con && !DataSourceUtils.isConnectionTransactional(con, ds)) { |
| | | DataSourceUtils.releaseConnection(con, ds); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return feature; |
| | | } |
| | | |
| | | /** |
| | | * æ°æ®æºå¯ä¸æ è¯ å¦æä¸å®ç°åé»è®¤feature |
| | | * @param datasource æ°æ®æº |
| | | * @return String è¿ånullç±ä¸å±èªå¨æå |
| | | */ |
| | | @Override |
| | | public String key(DataRuntime runtime, Object datasource) { |
| | | if(datasource instanceof JdbcTemplate jdbc){ |
| | | DataSource ds = jdbc.getDataSource(); |
| | | if(ds instanceof DynamicRoutingDataSource){ |
| | | return DynamicDataSourceContextHolder.peek(); |
| | | } |
| | | } |
| | | return runtime.getKey(); |
| | | } |
| | | |
| | | /** |
| | | * ConfigTable.KEEP_ADAPTER=2 : æ ¹æ®å½åæ¥å£å¤ææ¯å¦ä¿æåä¸ä¸ªæ°æ®æºç»å®åä¸ä¸ªadapter<br/> |
| | | * DynamicRoutingDataSourceç±»åçè¿åfalse,å 为åä¸ä¸ªDynamicRoutingDataSourceå¯è½å¯¹åºå¤ç±»æ°æ®åº, 妿项ç®ä¸åªæä¸ç§æ°æ®åº åºè¯¥ç´æ¥è¿åtrue |
| | | * |
| | | * @param datasource æ°æ®æº |
| | | * @return boolean |
| | | */ |
| | | @Override |
| | | public boolean keepAdapter(DataRuntime runtime, Object datasource) { |
| | | if (datasource instanceof JdbcTemplate jdbc) { |
| | | DataSource ds = jdbc.getDataSource(); |
| | | return !(ds instanceof DynamicRoutingDataSource); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | } |
| | |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @TableName("gen_table_column") |
| | |
| | | package org.dromara.generator.mapper; |
| | | |
| | | import com.baomidou.dynamic.datasource.annotation.DS; |
| | | import com.baomidou.mybatisplus.annotation.InterceptorIgnore; |
| | | import org.apache.ibatis.annotations.Param; |
| | | import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; |
| | | import org.dromara.generator.domain.GenTableColumn; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * ä¸å¡å段 æ°æ®å± |
| | |
| | | */ |
| | | @InterceptorIgnore(dataPermission = "true", tenantLine = "true") |
| | | public interface GenTableColumnMapper extends BaseMapperPlus<GenTableColumn, GenTableColumn> { |
| | | /** |
| | | * æ ¹æ®è¡¨åç§°æ¥è¯¢åä¿¡æ¯ |
| | | * |
| | | * @param tableName 表åç§° |
| | | * @param dataName æ°æ®æºåç§° |
| | | * @return åä¿¡æ¯ |
| | | */ |
| | | @DS("#dataName") |
| | | List<GenTableColumn> selectDbTableColumnsByName(@Param("tableName") String tableName, String dataName); |
| | | |
| | | } |
| | |
| | | public interface GenTableMapper extends BaseMapperPlus<GenTable, GenTable> { |
| | | |
| | | /** |
| | | * æ¥è¯¢æ®åºå表 |
| | | * |
| | | * @param genTable æ¥è¯¢æ¡ä»¶ |
| | | * @return æ°æ®åºè¡¨éå |
| | | */ |
| | | Page<GenTable> selectPageDbTableList(@Param("page") Page<GenTable> page, @Param("genTable") GenTable genTable); |
| | | |
| | | /** |
| | | * æ¥è¯¢æ®åºå表 |
| | | * |
| | | * @param tableNames 表åç§°ç» |
| | | * @return æ°æ®åºè¡¨éå |
| | | */ |
| | | List<GenTable> selectDbTableListByNames(String[] tableNames); |
| | | |
| | | /** |
| | | * æ¥è¯¢ææè¡¨ä¿¡æ¯ |
| | | * |
| | | * @return 表信æ¯éå |
| | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.anyline.metadata.Column; |
| | | import org.anyline.metadata.Table; |
| | | import org.anyline.proxy.ServiceProxy; |
| | | import org.apache.velocity.Template; |
| | | import org.apache.velocity.VelocityContext; |
| | | import org.apache.velocity.app.Velocity; |
| | | import org.dromara.common.core.constant.Constants; |
| | | import org.dromara.common.core.exception.ServiceException; |
| | | import org.dromara.common.core.utils.SpringUtils; |
| | | import org.dromara.common.core.utils.StreamUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.core.utils.file.FileUtils; |
| | |
| | | import java.io.IOException; |
| | | import java.io.StringWriter; |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.*; |
| | | import java.util.zip.ZipEntry; |
| | | import java.util.zip.ZipOutputStream; |
| | | |
| | |
| | | private final GenTableMapper baseMapper; |
| | | private final GenTableColumnMapper genTableColumnMapper; |
| | | private final IdentifierGenerator identifierGenerator; |
| | | |
| | | private static final String[] TABLE_IGNORE = new String[]{"sj_", "act_", "flw_", "gen_"}; |
| | | |
| | | /** |
| | | * æ¥è¯¢ä¸å¡å段å表 |
| | |
| | | Map<String, Object> params = genTable.getParams(); |
| | | QueryWrapper<GenTable> wrapper = Wrappers.query(); |
| | | wrapper |
| | | .eq(StringUtils.isNotEmpty(genTable.getDataName()),"data_name", genTable.getDataName()) |
| | | .eq(StringUtils.isNotEmpty(genTable.getDataName()), "data_name", genTable.getDataName()) |
| | | .like(StringUtils.isNotBlank(genTable.getTableName()), "lower(table_name)", StringUtils.lowerCase(genTable.getTableName())) |
| | | .like(StringUtils.isNotBlank(genTable.getTableComment()), "lower(table_comment)", StringUtils.lowerCase(genTable.getTableComment())) |
| | | .between(params.get("beginTime") != null && params.get("endTime") != null, |
| | |
| | | return wrapper; |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢æ°æ®åºå表 |
| | | * |
| | | * @param genTable å
嫿¥è¯¢æ¡ä»¶çGenTable对象 |
| | | * @param pageQuery å
å«å页信æ¯çPageQuery对象 |
| | | * @return å
å«åé¡µç»æçTableDataInfo对象 |
| | | */ |
| | | @DS("#genTable.dataName") |
| | | @Override |
| | | public TableDataInfo<GenTable> selectPageDbTableList(GenTable genTable, PageQuery pageQuery) { |
| | | genTable.getParams().put("genTableNames",baseMapper.selectTableNameList(genTable.getDataName())); |
| | | Page<GenTable> page = baseMapper.selectPageDbTableList(pageQuery.build(), genTable); |
| | | // è·åæ¥è¯¢æ¡ä»¶ |
| | | String tableName = genTable.getTableName(); |
| | | String tableComment = genTable.getTableComment(); |
| | | |
| | | LinkedHashMap<String, Table<?>> tablesMap = ServiceProxy.metadata().tables(); |
| | | if (CollUtil.isEmpty(tablesMap)) { |
| | | return TableDataInfo.build(); |
| | | } |
| | | List<String> tableNames = baseMapper.selectTableNameList(genTable.getDataName()); |
| | | String[] tableArrays; |
| | | if (CollUtil.isNotEmpty(tableNames)) { |
| | | tableArrays = tableNames.toArray(new String[0]); |
| | | } else { |
| | | tableArrays = new String[0]; |
| | | } |
| | | // è¿æ»¤å¹¶è½¬æ¢è¡¨æ ¼æ°æ® |
| | | List<GenTable> tables = tablesMap.values().stream() |
| | | .filter(x -> !StringUtils.containsAnyIgnoreCase(x.getName(), TABLE_IGNORE)) |
| | | .filter(x -> { |
| | | if (CollUtil.isEmpty(tableNames)) { |
| | | return true; |
| | | } |
| | | return !StringUtils.equalsAnyIgnoreCase(x.getName(), tableArrays); |
| | | }) |
| | | .filter(x -> { |
| | | boolean nameMatches = true; |
| | | boolean commentMatches = true; |
| | | // è¿è¡è¡¨åç§°çæ¨¡ç³æ¥è¯¢ |
| | | if (StringUtils.isNotBlank(tableName)) { |
| | | nameMatches = StringUtils.containsIgnoreCase(x.getName(), tableName); |
| | | } |
| | | // è¿è¡è¡¨æè¿°çæ¨¡ç³æ¥è¯¢ |
| | | if (StringUtils.isNotBlank(tableComment)) { |
| | | commentMatches = StringUtils.containsIgnoreCase(x.getComment(), tableComment); |
| | | } |
| | | // åæ¶å¹é
åç§°åæè¿° |
| | | return nameMatches && commentMatches; |
| | | }) |
| | | .map(x -> { |
| | | GenTable gen = new GenTable(); |
| | | gen.setTableName(x.getName()); |
| | | gen.setTableComment(x.getComment()); |
| | | gen.setCreateTime(x.getCreateTime()); |
| | | gen.setUpdateTime(x.getUpdateTime()); |
| | | return gen; |
| | | }).toList(); |
| | | |
| | | IPage<GenTable> page = pageQuery.build(); |
| | | page.setTotal(tables.size()); |
| | | // æå¨å页 setæ°æ® |
| | | page.setRecords(CollUtil.page((int) page.getCurrent() - 1, (int) page.getSize(), tables)); |
| | | return TableDataInfo.build(page); |
| | | } |
| | | |
| | |
| | | @DS("#dataName") |
| | | @Override |
| | | public List<GenTable> selectDbTableListByNames(String[] tableNames, String dataName) { |
| | | return baseMapper.selectDbTableListByNames(tableNames); |
| | | Set<String> tableNameSet = new HashSet<>(List.of(tableNames)); |
| | | LinkedHashMap<String, Table<?>> tablesMap = ServiceProxy.metadata().tables(); |
| | | |
| | | if (CollUtil.isEmpty(tablesMap)) { |
| | | return new ArrayList<>(); |
| | | } |
| | | |
| | | List<Table<?>> tableList = tablesMap.values().stream() |
| | | .filter(x -> !StringUtils.containsAnyIgnoreCase(x.getName(), TABLE_IGNORE)) |
| | | .filter(x -> tableNameSet.contains(x.getName())).toList(); |
| | | |
| | | if (CollUtil.isEmpty(tableList)) { |
| | | return new ArrayList<>(); |
| | | } |
| | | return tableList.stream().map(x -> { |
| | | GenTable gen = new GenTable(); |
| | | gen.setDataName(dataName); |
| | | gen.setTableName(x.getName()); |
| | | gen.setTableComment(x.getComment()); |
| | | gen.setCreateTime(x.getCreateTime()); |
| | | gen.setUpdateTime(x.getUpdateTime()); |
| | | return gen; |
| | | }).toList(); |
| | | } |
| | | |
| | | /** |
| | |
| | | int row = baseMapper.insert(table); |
| | | if (row > 0) { |
| | | // ä¿ååä¿¡æ¯ |
| | | List<GenTableColumn> genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName, dataName); |
| | | List<GenTableColumn> genTableColumns = SpringUtils.getAopProxy(this).selectDbTableColumnsByName(tableName, dataName); |
| | | List<GenTableColumn> saveColumns = new ArrayList<>(); |
| | | for (GenTableColumn column : genTableColumns) { |
| | | GenUtils.initColumnField(column, table); |
| | |
| | | } catch (Exception e) { |
| | | throw new ServiceException("导å
¥å¤±è´¥ï¼" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®è¡¨åç§°æ¥è¯¢åä¿¡æ¯ |
| | | * |
| | | * @param tableName 表åç§° |
| | | * @param dataName æ°æ®æºåç§° |
| | | * @return åä¿¡æ¯ |
| | | */ |
| | | @DS("#dataName") |
| | | @Override |
| | | public List<GenTableColumn> selectDbTableColumnsByName(String tableName, String dataName) { |
| | | LinkedHashMap<String, Column> columns = ServiceProxy.metadata().columns(tableName); |
| | | List<GenTableColumn> tableColumns = new ArrayList<>(); |
| | | columns.forEach((columnName, column) -> { |
| | | GenTableColumn tableColumn = new GenTableColumn(); |
| | | tableColumn.setIsPk(String.valueOf(column.isPrimaryKey())); |
| | | tableColumn.setColumnName(column.getName()); |
| | | tableColumn.setColumnComment(column.getComment()); |
| | | tableColumn.setColumnType(column.getTypeName().toLowerCase()); |
| | | tableColumn.setSort(column.getPosition()); |
| | | tableColumn.setIsRequired(column.isNullable() == 0 ? "1" : "0"); |
| | | tableColumn.setIsIncrement(column.isAutoIncrement() == -1 ? "0" : "1"); |
| | | tableColumns.add(tableColumn); |
| | | }); |
| | | return tableColumns; |
| | | } |
| | | |
| | | /** |
| | |
| | | List<GenTableColumn> tableColumns = table.getColumns(); |
| | | Map<String, GenTableColumn> tableColumnMap = StreamUtils.toIdentityMap(tableColumns, GenTableColumn::getColumnName); |
| | | |
| | | List<GenTableColumn> dbTableColumns = genTableColumnMapper.selectDbTableColumnsByName(table.getTableName(), table.getDataName()); |
| | | List<GenTableColumn> dbTableColumns = SpringUtils.getAopProxy(this).selectDbTableColumnsByName(table.getTableName(), table.getDataName()); |
| | | if (CollUtil.isEmpty(dbTableColumns)) { |
| | | throw new ServiceException("åæ¥æ°æ®å¤±è´¥ï¼åè¡¨ç»æä¸åå¨"); |
| | | } |
| | |
| | | void importGenTable(List<GenTable> tableList, String dataName); |
| | | |
| | | /** |
| | | * æ ¹æ®è¡¨åç§°æ¥è¯¢åä¿¡æ¯ |
| | | * |
| | | * @param tableName 表åç§° |
| | | * @param dataName æ°æ®æºåç§° |
| | | * @return åä¿¡æ¯ |
| | | */ |
| | | List<GenTableColumn> selectDbTableColumnsByName(String tableName, String dataName); |
| | | |
| | | /** |
| | | * é¢è§ä»£ç |
| | | * |
| | | * @param tableId 表ç¼å· |
| | |
| | | importList.add("com.fasterxml.jackson.annotation.JsonFormat"); |
| | | } else if (!column.isSuperColumn() && GenConstants.TYPE_BIGDECIMAL.equals(column.getJavaType())) { |
| | | importList.add("java.math.BigDecimal"); |
| | | } else if (!column.isSuperColumn() && "imageUpload".equals(column.getHtmlType())) { |
| | | importList.add("org.dromara.common.translation.annotation.Translation"); |
| | | importList.add("org.dromara.common.translation.constant.TransConstant"); |
| | | } |
| | | } |
| | | return importList; |
| | |
| | | <resultMap type="org.dromara.generator.domain.GenTableColumn" id="GenTableColumnResult"> |
| | | </resultMap> |
| | | |
| | | <select id="selectDbTableColumnsByName" parameterType="String" resultMap="GenTableColumnResult"> |
| | | <if test="@org.dromara.common.mybatis.helper.DataBaseHelper@isMySql()"> |
| | | select column_name, |
| | | (case when (is_nullable = 'no' <![CDATA[ && ]]> column_key != 'PRI') then '1' else '0' end) as is_required, |
| | | (case when column_key = 'PRI' then '1' else '0' end) as is_pk, |
| | | ordinal_position as sort, |
| | | column_comment, |
| | | (case when extra = 'auto_increment' then '1' else '0' end) as is_increment, |
| | | column_type |
| | | from information_schema.columns where table_schema = (select database()) and table_name = (#{tableName}) |
| | | order by ordinal_position |
| | | </if> |
| | | <if test="@org.dromara.common.mybatis.helper.DataBaseHelper@isOracle()"> |
| | | select lower(temp.column_name) as column_name, |
| | | (case when (temp.nullable = 'N' and temp.constraint_type != 'P') then '1' else '0' end) as is_required, |
| | | (case when temp.constraint_type = 'P' then '1' else '0' end) as is_pk, |
| | | temp.column_id as sort, |
| | | temp.comments as column_comment, |
| | | (case when temp.constraint_type = 'P' then '1' else '0' end) as is_increment, |
| | | lower(temp.data_type) as column_type |
| | | from ( |
| | | select col.column_id, col.column_name,col.nullable, col.data_type, colc.comments, uc.constraint_type, row_number() |
| | | over (partition by col.column_name order by uc.constraint_type desc) as row_flg |
| | | from user_tab_columns col |
| | | left join user_col_comments colc on colc.table_name = col.table_name and colc.column_name = col.column_name |
| | | left join user_cons_columns ucc on ucc.table_name = col.table_name and ucc.column_name = col.column_name |
| | | left join user_constraints uc on uc.constraint_name = ucc.constraint_name |
| | | where col.table_name = upper(#{tableName}) |
| | | ) temp |
| | | WHERE temp.row_flg = 1 |
| | | ORDER BY temp.column_id |
| | | </if> |
| | | <if test="@org.dromara.common.mybatis.helper.DataBaseHelper@isPostgerSql()"> |
| | | SELECT column_name, is_required, is_pk, sort, column_comment, is_increment, column_type |
| | | FROM ( |
| | | SELECT c.relname AS table_name, |
| | | a.attname AS column_name, |
| | | d.description AS column_comment, |
| | | CASE WHEN a.attnotnull AND con.conname IS NULL THEN 1 ELSE 0 |
| | | END AS is_required, |
| | | CASE WHEN con.conname IS NOT NULL THEN 1 ELSE 0 |
| | | END AS is_pk, |
| | | a.attnum AS sort, |
| | | CASE WHEN "position"(pg_get_expr(ad.adbin, ad.adrelid), |
| | | ((c.relname::text || '_'::text) || a.attname::text) || '_seq'::text) > 0 THEN 1 ELSE 0 |
| | | END AS is_increment, |
| | | btrim( |
| | | CASE WHEN t.typelem <![CDATA[ <> ]]> 0::oid AND t.typlen = '-1'::integer THEN 'ARRAY'::text ELSE |
| | | CASE WHEN t.typtype = 'd'::"char" THEN format_type(t.typbasetype, NULL::integer) |
| | | ELSE format_type(a.atttypid, NULL::integer) END |
| | | END, '"'::text |
| | | ) AS column_type |
| | | FROM pg_attribute a |
| | | JOIN (pg_class c JOIN pg_namespace n ON c.relnamespace = n.oid) ON a.attrelid = c.oid |
| | | LEFT JOIN pg_description d ON d.objoid = c.oid AND a.attnum = d.objsubid |
| | | LEFT JOIN pg_constraint con ON con.conrelid = c.oid AND (a.attnum = ANY (con.conkey)) |
| | | LEFT JOIN pg_attrdef ad ON a.attrelid = ad.adrelid AND a.attnum = ad.adnum |
| | | LEFT JOIN pg_type t ON a.atttypid = t.oid |
| | | WHERE (c.relkind = ANY (ARRAY ['r'::"char", 'p'::"char"])) |
| | | AND a.attnum > 0 |
| | | AND n.nspname = 'public'::name |
| | | ORDER BY c.relname, a.attnum |
| | | ) temp |
| | | WHERE table_name = (#{tableName}) |
| | | AND column_type <![CDATA[ <> ]]> '-' |
| | | </if> |
| | | <if test="@org.dromara.common.mybatis.helper.DataBaseHelper@isSqlServer()"> |
| | | SELECT |
| | | cast(A.NAME as nvarchar) as column_name, |
| | | cast(B.NAME as nvarchar) + (case when B.NAME = 'numeric' then '(' + cast(A.prec as nvarchar) + ',' + cast(A.scale as nvarchar) + ')' else '' end) as column_type, |
| | | cast(G.[VALUE] as nvarchar) as column_comment, |
| | | (SELECT 1 FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE Z WHERE TABLE_NAME = D.NAME and A.NAME = Z.column_name ) as is_pk, |
| | | colorder as sort |
| | | FROM SYSCOLUMNS A |
| | | LEFT JOIN SYSTYPES B ON A.XTYPE = B.XUSERTYPE |
| | | INNER JOIN SYSOBJECTS D ON A.ID = D.ID AND D.XTYPE='U' AND D.NAME != 'DTPROPERTIES' |
| | | LEFT JOIN SYS.EXTENDED_PROPERTIES G ON A.ID = G.MAJOR_ID AND A.COLID = G.MINOR_ID |
| | | LEFT JOIN SYS.EXTENDED_PROPERTIES F ON D.ID = F.MAJOR_ID AND F.MINOR_ID = 0 |
| | | WHERE D.NAME = #{tableName} |
| | | ORDER BY A.COLORDER |
| | | </if> |
| | | </select> |
| | | |
| | | </mapper> |
| | |
| | | <id property="columnId" column="column_id"/> |
| | | </resultMap> |
| | | |
| | | <select id="selectPageDbTableList" resultMap="GenTableResult"> |
| | | <if test="@org.dromara.common.mybatis.helper.DataBaseHelper@isMySql()"> |
| | | select table_name, table_comment, create_time, update_time |
| | | from information_schema.tables |
| | | where table_schema = (select database()) |
| | | AND table_name NOT LIKE 'sj_%' AND table_name NOT LIKE 'gen_%' |
| | | AND table_name NOT LIKE 'act_%' AND table_name NOT LIKE 'flw_%' |
| | | <if test="genTable.params.genTableNames != null and genTable.params.genTableNames.size > 0"> |
| | | AND table_name NOT IN |
| | | <foreach collection="genTable.params.genTableNames" open="(" close=")" separator="," item="item"> |
| | | #{item} |
| | | </foreach> |
| | | </if> |
| | | <if test="genTable.tableName != null and genTable.tableName != ''"> |
| | | AND lower(table_name) like lower(concat('%', #{genTable.tableName}, '%')) |
| | | </if> |
| | | <if test="genTable.tableComment != null and genTable.tableComment != ''"> |
| | | AND lower(table_comment) like lower(concat('%', #{genTable.tableComment}, '%')) |
| | | </if> |
| | | order by create_time desc |
| | | </if> |
| | | <if test="@org.dromara.common.mybatis.helper.DataBaseHelper@isOracle()"> |
| | | select lower(dt.table_name) as table_name, dtc.comments as table_comment, uo.created as create_time, uo.last_ddl_time as update_time |
| | | from user_tables dt, user_tab_comments dtc, user_objects uo |
| | | where dt.table_name = dtc.table_name |
| | | and dt.table_name = uo.object_name |
| | | and uo.object_type = 'TABLE' |
| | | AND dt.table_name NOT LIKE 'SJ_%' AND dt.table_name NOT LIKE 'GEN_%' |
| | | AND dt.table_name NOT LIKE 'ACT_%' AND dt.table_name NOT LIKE 'FLW_%' |
| | | <if test="genTable.params.genTableNames != null and genTable.params.genTableNames.size > 0"> |
| | | AND lower(dt.table_name) NOT IN |
| | | <foreach collection="genTable.params.genTableNames" open="(" close=")" separator="," item="item"> |
| | | #{item} |
| | | </foreach> |
| | | </if> |
| | | <if test="genTable.tableName != null and genTable.tableName != ''"> |
| | | AND lower(dt.table_name) like lower(concat(concat('%', #{genTable.tableName}), '%')) |
| | | </if> |
| | | <if test="genTable.tableComment != null and genTable.tableComment != ''"> |
| | | AND lower(dtc.comments) like lower(concat(concat('%', #{genTable.tableComment}), '%')) |
| | | </if> |
| | | order by create_time desc |
| | | </if> |
| | | <if test="@org.dromara.common.mybatis.helper.DataBaseHelper@isPostgerSql()"> |
| | | select table_name, table_comment, create_time, update_time |
| | | from ( |
| | | SELECT c.relname AS table_name, |
| | | obj_description(c.oid) AS table_comment, |
| | | CURRENT_TIMESTAMP AS create_time, |
| | | CURRENT_TIMESTAMP AS update_time |
| | | FROM pg_class c |
| | | LEFT JOIN pg_namespace n ON n.oid = c.relnamespace |
| | | WHERE (c.relkind = ANY (ARRAY ['r'::"char", 'p'::"char"])) |
| | | AND c.relname != 'spatial_%'::text |
| | | AND n.nspname = 'public'::name |
| | | AND n.nspname <![CDATA[ <> ]]> ''::name |
| | | ) list_table |
| | | where table_name NOT LIKE 'sj_%' AND table_name NOT LIKE 'gen_%' |
| | | AND table_name NOT LIKE 'act_%' AND table_name NOT LIKE 'flw_%' |
| | | <if test="genTable.params.genTableNames != null and genTable.params.genTableNames.size > 0"> |
| | | AND table_name NOT IN |
| | | <foreach collection="genTable.params.genTableNames" open="(" close=")" separator="," item="item"> |
| | | #{item} |
| | | </foreach> |
| | | </if> |
| | | <if test="genTable.tableName != null and genTable.tableName != ''"> |
| | | AND lower(table_name) like lower(concat('%', #{genTable.tableName}, '%')) |
| | | </if> |
| | | <if test="genTable.tableComment != null and genTable.tableComment != ''"> |
| | | AND lower(table_comment) like lower(concat('%', #{genTable.tableComment}, '%')) |
| | | </if> |
| | | order by create_time desc |
| | | </if> |
| | | <if test="@org.dromara.common.mybatis.helper.DataBaseHelper@isSqlServer()"> |
| | | SELECT cast(D.NAME as nvarchar) as table_name, |
| | | cast(F.VALUE as nvarchar) as table_comment, |
| | | crdate as create_time, |
| | | refdate as update_time |
| | | FROM SYSOBJECTS D |
| | | INNER JOIN SYS.EXTENDED_PROPERTIES F ON D.ID = F.MAJOR_ID |
| | | AND F.MINOR_ID = 0 AND D.XTYPE = 'U' AND D.NAME != 'DTPROPERTIES' |
| | | AND D.NAME NOT LIKE 'sj_%' AND D.NAME NOT LIKE 'gen_%' |
| | | AND D.NAME NOT LIKE 'act_%' AND D.NAME NOT LIKE 'flw_%' |
| | | <if test="genTable.params.genTableNames != null and genTable.params.genTableNames.size > 0"> |
| | | AND D.NAME NOT IN |
| | | <foreach collection="genTable.params.genTableNames" open="(" close=")" separator="," item="item"> |
| | | #{item} |
| | | </foreach> |
| | | </if> |
| | | <if test="genTable.tableName != null and genTable.tableName != ''"> |
| | | AND lower(D.NAME) like lower(concat(N'%', N'${genTable.tableName}', N'%')) |
| | | </if> |
| | | <if test="genTable.tableComment != null and genTable.tableComment != ''"> |
| | | AND lower(CAST(F.VALUE AS nvarchar)) like lower(concat(N'%', N'${genTable.tableComment}', N'%')) |
| | | </if> |
| | | order by crdate desc |
| | | </if> |
| | | </select> |
| | | |
| | | <select id="selectDbTableListByNames" resultMap="GenTableResult"> |
| | | <if test="@org.dromara.common.mybatis.helper.DataBaseHelper@isMySql()"> |
| | | select table_name, table_comment, create_time, update_time from information_schema.tables |
| | | where table_schema = (select database()) |
| | | and table_name NOT LIKE 'sj_%' and table_name NOT LIKE 'gen_%' |
| | | and table_name NOT LIKE 'act_%' AND table_name NOT LIKE 'flw_%' |
| | | and table_name in |
| | | <foreach collection="array" item="name" open="(" separator="," close=")"> |
| | | #{name} |
| | | </foreach> |
| | | </if> |
| | | <if test="@org.dromara.common.mybatis.helper.DataBaseHelper@isOracle()"> |
| | | select lower(dt.table_name) as table_name, dtc.comments as table_comment, uo.created as create_time, uo.last_ddl_time as update_time |
| | | from user_tables dt, user_tab_comments dtc, user_objects uo |
| | | where dt.table_name = dtc.table_name |
| | | and dt.table_name = uo.object_name |
| | | and uo.object_type = 'TABLE' |
| | | and dt.table_name NOT LIKE 'SJ_%' AND dt.table_name NOT LIKE 'GEN_%' |
| | | and dt.table_name NOT LIKE 'ACT_%' AND dt.table_name NOT LIKE 'FLW_%' |
| | | and lower(dt.table_name) in |
| | | <foreach collection="array" item="name" open="(" separator="," close=")"> |
| | | #{name} |
| | | </foreach> |
| | | </if> |
| | | <if test="@org.dromara.common.mybatis.helper.DataBaseHelper@isPostgerSql()"> |
| | | select table_name, table_comment, create_time, update_time |
| | | from ( |
| | | SELECT c.relname AS table_name, |
| | | obj_description(c.oid) AS table_comment, |
| | | CURRENT_TIMESTAMP AS create_time, |
| | | CURRENT_TIMESTAMP AS update_time |
| | | FROM pg_class c |
| | | LEFT JOIN pg_namespace n ON n.oid = c.relnamespace |
| | | WHERE (c.relkind = ANY (ARRAY ['r'::"char", 'p'::"char"])) |
| | | AND c.relname != 'spatial_%'::text |
| | | AND n.nspname = 'public'::name |
| | | AND n.nspname <![CDATA[ <> ]]> ''::name |
| | | ) list_table |
| | | where table_name NOT LIKE 'sj_%' and table_name NOT LIKE 'gen_%' |
| | | and table_name NOT LIKE 'act_%' and table_name NOT LIKE 'flw_%' |
| | | and table_name in |
| | | <foreach collection="array" item="name" open="(" separator="," close=")"> |
| | | #{name} |
| | | </foreach> |
| | | </if> |
| | | <if test="@org.dromara.common.mybatis.helper.DataBaseHelper@isSqlServer()"> |
| | | SELECT cast(D.NAME as nvarchar) as table_name, |
| | | cast(F.VALUE as nvarchar) as table_comment, |
| | | crdate as create_time, |
| | | refdate as update_time |
| | | FROM SYSOBJECTS D |
| | | INNER JOIN SYS.EXTENDED_PROPERTIES F ON D.ID = F.MAJOR_ID |
| | | AND F.MINOR_ID = 0 AND D.XTYPE = 'U' AND D.NAME != 'DTPROPERTIES' |
| | | AND D.NAME NOT LIKE 'sj_%' AND D.NAME NOT LIKE 'gen_%' |
| | | AND D.NAME NOT LIKE 'act_%' AND D.NAME NOT LIKE 'flw_%' |
| | | AND D.NAME in |
| | | <foreach collection="array" item="name" open="(" separator="," close=")"> |
| | | #{name} |
| | | </foreach> |
| | | </if> |
| | | </select> |
| | | |
| | | <select id="selectTableByName" parameterType="String" resultMap="GenTableResult"> |
| | | <if test="@org.dromara.common.mybatis.helper.DataBaseHelper@isMySql()"> |
| | | select table_name, table_comment, create_time, update_time from information_schema.tables |
| | | where table_schema = (select database()) |
| | | and table_name NOT LIKE 'sj_%' and table_name NOT LIKE 'gen_%' |
| | | and table_name NOT LIKE 'act_%' AND table_name NOT LIKE 'flw_%' |
| | | and table_name = #{tableName} |
| | | </if> |
| | | <if test="@org.dromara.common.mybatis.helper.DataBaseHelper@isOracle()"> |
| | | select lower(dt.table_name) as table_name, dtc.comments as table_comment, uo.created as create_time, uo.last_ddl_time as update_time |
| | | from user_tables dt, user_tab_comments dtc, user_objects uo |
| | | where dt.table_name = dtc.table_name |
| | | and dt.table_name = uo.object_name |
| | | and uo.object_type = 'TABLE' |
| | | AND dt.table_name NOT LIKE 'SJ_%' AND dt.table_name NOT LIKE 'GEN_%' |
| | | AND dt.table_name NOT LIKE 'ACT_%' AND dt.table_name NOT LIKE 'FLW_%' |
| | | AND dt.table_name NOT IN (select table_name from gen_table) |
| | | and lower(dt.table_name) = #{tableName} |
| | | </if> |
| | | <if test="@org.dromara.common.mybatis.helper.DataBaseHelper@isPostgerSql()"> |
| | | select table_name, table_comment, create_time, update_time |
| | | from ( |
| | | SELECT c.relname AS table_name, |
| | | obj_description(c.oid) AS table_comment, |
| | | CURRENT_TIMESTAMP AS create_time, |
| | | CURRENT_TIMESTAMP AS update_time |
| | | FROM pg_class c |
| | | LEFT JOIN pg_namespace n ON n.oid = c.relnamespace |
| | | WHERE (c.relkind = ANY (ARRAY ['r'::"char", 'p'::"char"])) |
| | | AND c.relname != 'spatial_%'::text |
| | | AND n.nspname = 'public'::name |
| | | AND n.nspname <![CDATA[ <> ]]> ''::name |
| | | ) list_table |
| | | where table_name NOT LIKE 'sj_%' and table_name NOT LIKE 'gen_%' |
| | | and table_name NOT LIKE 'act_%' and table_name NOT LIKE 'flw_%' |
| | | and table_name = #{tableName} |
| | | </if> |
| | | <if test="@org.dromara.common.mybatis.helper.DataBaseHelper@isSqlServer()"> |
| | | SELECT cast(D.NAME as nvarchar) as table_name, |
| | | cast(F.VALUE as nvarchar) as table_comment, |
| | | crdate as create_time, |
| | | refdate as update_time |
| | | FROM SYSOBJECTS D |
| | | INNER JOIN SYS.EXTENDED_PROPERTIES F ON D.ID = F.MAJOR_ID |
| | | AND F.MINOR_ID = 0 AND D.XTYPE = 'U' AND D.NAME != 'DTPROPERTIES' |
| | | AND D.NAME NOT LIKE 'sj_%' AND D.NAME NOT LIKE 'gen_%' |
| | | AND D.NAME NOT LIKE 'act_%' AND D.NAME NOT LIKE 'flw_%' |
| | | AND D.NAME = #{tableName} |
| | | </if> |
| | | </select> |
| | | |
| | | <select id="selectGenTableById" parameterType="Long" resultMap="GenTableResult"> |
| | | <sql id="genSelect"> |
| | | SELECT t.table_id, t.data_name, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark, |
| | | c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort |
| | | FROM gen_table t |
| | | LEFT JOIN gen_table_column c ON t.table_id = c.table_id |
| | | LEFT JOIN gen_table_column c ON t.table_id = c.table_id |
| | | </sql> |
| | | |
| | | <select id="selectGenTableById" parameterType="Long" resultMap="GenTableResult"> |
| | | <include refid="genSelect"/> |
| | | where t.table_id = #{tableId} order by c.sort |
| | | </select> |
| | | |
| | | <select id="selectGenTableByName" parameterType="String" resultMap="GenTableResult"> |
| | | SELECT t.table_id, t.data_name, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark, |
| | | c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort |
| | | FROM gen_table t |
| | | LEFT JOIN gen_table_column c ON t.table_id = c.table_id |
| | | <include refid="genSelect"/> |
| | | where t.table_name = #{tableName} order by c.sort |
| | | </select> |
| | | |
| | | <select id="selectGenTableAll" parameterType="String" resultMap="GenTableResult"> |
| | | SELECT t.table_id, t.data_name, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.options, t.remark, |
| | | c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort |
| | | FROM gen_table t |
| | | LEFT JOIN gen_table_column c ON t.table_id = c.table_id |
| | | <include refid="genSelect"/> |
| | | order by c.sort |
| | | </select> |
| | | |
| | |
| | | #end |
| | | private $column.javaType $column.javaField; |
| | | |
| | | #if($column.htmlType == "imageUpload") |
| | | /** |
| | | * ${column.columnComment}Url |
| | | */ |
| | | @Translation(type = TransConstant.OSS_ID_TO_URL, mapper = "${column.javaField}") |
| | | private String ${column.javaField}Url"; |
| | | #end |
| | | #end |
| | | #end |
| | | |
| | |
| | | #elseif($column.javaType == 'Boolean') boolean; |
| | | #else string; |
| | | #end |
| | | #if($column.htmlType == "imageUpload") |
| | | /** |
| | | * ${column.columnComment}Url |
| | | */ |
| | | ${column.javaField}Url: string; |
| | | #end |
| | | #end |
| | | #end |
| | | #if ($table.tree) |
| | |
| | | </template> |
| | | </el-table-column> |
| | | #elseif($column.list && $column.htmlType == "imageUpload") |
| | | <el-table-column label="${comment}" align="center" prop="${javaField}" width="100"> |
| | | <el-table-column label="${comment}" align="center" prop="${javaField}Url" width="100"> |
| | | <template #default="scope"> |
| | | <image-preview :src="scope.row.${javaField}" :width="50" :height="50"/> |
| | | <image-preview :src="scope.row.${javaField}Url" :width="50" :height="50"/> |
| | | </template> |
| | | </el-table-column> |
| | | #elseif($column.list && $column.dictType && "" != $column.dictType) |
| | |
| | | </template> |
| | | </el-table-column> |
| | | #elseif($column.list && $column.htmlType == "imageUpload") |
| | | <el-table-column label="${comment}" align="center" prop="${javaField}" width="100"> |
| | | <el-table-column label="${comment}" align="center" prop="${javaField}Url" width="100"> |
| | | <template #default="scope"> |
| | | <image-preview :src="scope.row.${javaField}" :width="50" :height="50"/> |
| | | <image-preview :src="scope.row.${javaField}Url" :width="50" :height="50"/> |
| | | </template> |
| | | </el-table-column> |
| | | #elseif($column.list && $column.dictType && "" != $column.dictType) |
| | |
| | | <artifactId>ruoyi-common-websocket</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-sse</artifactId> |
| | | </dependency> |
| | | |
| | | </dependencies> |
| | | |
| | | </project> |
| | |
| | | package org.dromara.system.controller.monitor; |
| | | |
| | | import cn.dev33.satoken.annotation.SaCheckPermission; |
| | | import org.dromara.common.core.constant.GlobalConstants; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.dromara.common.core.constant.CacheConstants; |
| | | import org.dromara.common.core.domain.R; |
| | | import org.dromara.common.excel.utils.ExcelUtil; |
| | | import org.dromara.common.log.annotation.Log; |
| | |
| | | import org.dromara.system.domain.bo.SysLogininforBo; |
| | | import org.dromara.system.domain.vo.SysLogininforVo; |
| | | import org.dromara.system.service.ISysLogininforService; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | |
| | | @Log(title = "è´¦æ·è§£é", businessType = BusinessType.OTHER) |
| | | @GetMapping("/unlock/{userName}") |
| | | public R<Void> unlock(@PathVariable("userName") String userName) { |
| | | String loginName = GlobalConstants.PWD_ERR_CNT_KEY + userName; |
| | | String loginName = CacheConstants.PWD_ERR_CNT_KEY + userName; |
| | | if (RedisUtils.hasKey(loginName)) { |
| | | RedisUtils.deleteObject(loginName); |
| | | } |
| | |
| | | import org.dromara.system.domain.bo.SysDeptBo; |
| | | import org.dromara.system.domain.vo.SysDeptVo; |
| | | import org.dromara.system.service.ISysDeptService; |
| | | import org.dromara.system.service.ISysPostService; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | |
| | | public class SysDeptController extends BaseController { |
| | | |
| | | private final ISysDeptService deptService; |
| | | private final ISysPostService postService; |
| | | |
| | | /** |
| | | * è·åé¨é¨å表 |
| | |
| | | if (deptService.checkDeptExistUser(deptId)) { |
| | | return R.warn("é¨é¨åå¨ç¨æ·,ä¸å
许å é¤"); |
| | | } |
| | | if (postService.countPostByDeptId(deptId) > 0) { |
| | | return R.warn("é¨é¨åå¨å²ä½,ä¸å
许å é¤"); |
| | | } |
| | | deptService.checkDeptDataScope(deptId); |
| | | return toAjax(deptService.deleteDeptById(deptId)); |
| | | } |
| | |
| | | import org.dromara.common.log.enums.BusinessType; |
| | | import org.dromara.common.mybatis.core.page.PageQuery; |
| | | import org.dromara.common.mybatis.core.page.TableDataInfo; |
| | | import org.dromara.common.sse.utils.SseMessageUtils; |
| | | import org.dromara.common.web.core.BaseController; |
| | | import org.dromara.common.websocket.utils.WebSocketUtils; |
| | | import org.dromara.system.domain.bo.SysNoticeBo; |
| | | import org.dromara.system.domain.vo.SysNoticeVo; |
| | | import org.dromara.system.service.ISysNoticeService; |
| | |
| | | return R.fail(); |
| | | } |
| | | String type = dictService.getDictLabel("sys_notice_type", notice.getNoticeType()); |
| | | WebSocketUtils.publishAll("[" + type + "] " + notice.getNoticeTitle()); |
| | | SseMessageUtils.publishAll("[" + type + "] " + notice.getNoticeTitle()); |
| | | return R.ok(); |
| | | } |
| | | |
| | |
| | | import org.dromara.common.idempotent.annotation.RepeatSubmit; |
| | | import org.dromara.common.log.annotation.Log; |
| | | import org.dromara.common.log.enums.BusinessType; |
| | | import org.dromara.common.mybatis.helper.DataPermissionHelper; |
| | | import org.dromara.common.satoken.utils.LoginHelper; |
| | | import org.dromara.common.web.core.BaseController; |
| | | import org.dromara.system.domain.bo.SysUserBo; |
| | |
| | | if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { |
| | | return R.fail("ä¿®æ¹ç¨æ·'" + username + "'失败ï¼é®ç®±è´¦å·å·²åå¨"); |
| | | } |
| | | if (userService.updateUserProfile(user) > 0) { |
| | | int rows = DataPermissionHelper.ignore(() -> userService.updateUserProfile(user)); |
| | | if (rows > 0) { |
| | | return R.ok(); |
| | | } |
| | | return R.fail("ä¿®æ¹ä¸ªäººä¿¡æ¯å¼å¸¸ï¼è¯·è系管çå"); |
| | |
| | | import org.dromara.system.domain.bo.SysTenantBo; |
| | | import org.dromara.system.domain.vo.SysTenantVo; |
| | | import org.dromara.system.service.ISysTenantService; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | |
| | | @RequiredArgsConstructor |
| | | @RestController |
| | | @RequestMapping("/system/tenant") |
| | | @ConditionalOnProperty(value = "tenant.enable", havingValue = "true") |
| | | public class SysTenantController extends BaseController { |
| | | |
| | | private final ISysTenantService tenantService; |
| | |
| | | import jakarta.validation.constraints.NotEmpty; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | |
| | | @RequiredArgsConstructor |
| | | @RestController |
| | | @RequestMapping("/system/tenant/package") |
| | | @ConditionalOnProperty(value = "tenant.enable", havingValue = "true") |
| | | public class SysTenantPackageController extends BaseController { |
| | | |
| | | private final ISysTenantPackageService tenantPackageService; |
| | |
| | | @RepeatSubmit() |
| | | @PostMapping() |
| | | public R<Void> add(@Validated(AddGroup.class) @RequestBody SysTenantPackageBo bo) { |
| | | if (!tenantPackageService.checkPackageNameUnique(bo)) { |
| | | return R.fail("æ°å¢å¥é¤'" + bo.getPackageName() + "'失败ï¼å¥é¤åç§°å·²åå¨"); |
| | | } |
| | | return toAjax(tenantPackageService.insertByBo(bo)); |
| | | } |
| | | |
| | |
| | | @RepeatSubmit() |
| | | @PutMapping() |
| | | public R<Void> edit(@Validated(EditGroup.class) @RequestBody SysTenantPackageBo bo) { |
| | | if (!tenantPackageService.checkPackageNameUnique(bo)) { |
| | | return R.fail("ä¿®æ¹å¥é¤'" + bo.getPackageName() + "'失败ï¼å¥é¤åç§°å·²åå¨"); |
| | | } |
| | | return toAjax(tenantPackageService.updateByBo(bo)); |
| | | } |
| | | |
| | |
| | | /** |
| | | * ç¨æ·é®ç®± |
| | | */ |
| | | @Sensitive(strategy = SensitiveStrategy.EMAIL) |
| | | @Sensitive(strategy = SensitiveStrategy.EMAIL, perms = "system:user:edit") |
| | | private String email; |
| | | |
| | | /** |
| | | * ææºå·ç |
| | | */ |
| | | @Sensitive(strategy = SensitiveStrategy.PHONE) |
| | | @Sensitive(strategy = SensitiveStrategy.PHONE, perms = "system:user:edit") |
| | | private String phonenumber; |
| | | |
| | | /** |
| | |
| | | long countUserPostById(Long postId); |
| | | |
| | | /** |
| | | * éè¿é¨é¨IDæ¥è¯¢å²ä½ä½¿ç¨æ°é |
| | | * |
| | | * @param deptId é¨é¨id |
| | | * @return ç»æ |
| | | */ |
| | | long countPostByDeptId(Long deptId); |
| | | |
| | | /** |
| | | * å é¤å²ä½ä¿¡æ¯ |
| | | * |
| | | * @param postId å²ä½ID |
| | |
| | | package org.dromara.system.service; |
| | | |
| | | import org.dromara.system.domain.vo.SysTenantPackageVo; |
| | | import org.dromara.system.domain.bo.SysTenantPackageBo; |
| | | import org.dromara.common.mybatis.core.page.TableDataInfo; |
| | | import org.dromara.common.mybatis.core.page.PageQuery; |
| | | import org.dromara.common.mybatis.core.page.TableDataInfo; |
| | | import org.dromara.system.domain.bo.SysTenantPackageBo; |
| | | import org.dromara.system.domain.vo.SysTenantPackageVo; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | |
| | | Boolean updateByBo(SysTenantPackageBo bo); |
| | | |
| | | /** |
| | | * æ ¡éªå¥é¤åç§°æ¯å¦å¯ä¸ |
| | | */ |
| | | boolean checkPackageNameUnique(SysTenantPackageBo bo); |
| | | |
| | | /** |
| | | * ä¿®æ¹å¥é¤ç¶æ |
| | | */ |
| | | int updatePackageStatus(SysTenantPackageBo bo); |
| | |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.convert.Convert; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.dromara.common.core.utils.StreamUtils; |
| | |
| | | */ |
| | | @Override |
| | | public String getRoleCustom(Long roleId) { |
| | | if (ObjectUtil.isNull(roleId)) { |
| | | return "-1"; |
| | | } |
| | | List<SysRoleDept> list = roleDeptMapper.selectList( |
| | | new LambdaQueryWrapper<SysRoleDept>() |
| | | .select(SysRoleDept::getDeptId) |
| | |
| | | if (CollUtil.isNotEmpty(list)) { |
| | | return StreamUtils.join(list, rd -> Convert.toStr(rd.getDeptId())); |
| | | } |
| | | return null; |
| | | return "-1"; |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | @Override |
| | | public String getDeptAndChild(Long deptId) { |
| | | if (ObjectUtil.isNull(deptId)) { |
| | | return "-1"; |
| | | } |
| | | List<SysDept> deptList = deptMapper.selectList(new LambdaQueryWrapper<SysDept>() |
| | | .select(SysDept::getDeptId) |
| | | .apply(DataBaseHelper.findInSet(deptId, "ancestors"))); |
| | |
| | | if (CollUtil.isNotEmpty(ids)) { |
| | | return StreamUtils.join(ids, Convert::toStr); |
| | | } |
| | | return null; |
| | | return "-1"; |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | private LambdaQueryWrapper<SysDept> buildQueryWrapper(SysDeptBo bo) { |
| | | LambdaQueryWrapper<SysDept> lqw = Wrappers.lambdaQuery(); |
| | | lqw.eq(SysDept::getDelFlag, "0"); |
| | | lqw.eq(SysDept::getDelFlag, UserConstants.DEL_FLAG_NORMAL); |
| | | lqw.eq(ObjectUtil.isNotNull(bo.getDeptId()), SysDept::getDeptId, bo.getDeptId()); |
| | | lqw.eq(ObjectUtil.isNotNull(bo.getParentId()), SysDept::getParentId, bo.getParentId()); |
| | | lqw.like(StringUtils.isNotBlank(bo.getDeptName()), SysDept::getDeptName, bo.getDeptName()); |
| | |
| | | @Override |
| | | public List<SysOssVo> listByIds(Collection<Long> ossIds) { |
| | | List<SysOssVo> list = new ArrayList<>(); |
| | | SysOssServiceImpl ossService = SpringUtils.getAopProxy(this); |
| | | for (Long id : ossIds) { |
| | | SysOssVo vo = SpringUtils.getAopProxy(this).getById(id); |
| | | SysOssVo vo = ossService.getById(id); |
| | | if (ObjectUtil.isNotNull(vo)) { |
| | | try { |
| | | list.add(this.matchingUrl(vo)); |
| | |
| | | @Override |
| | | public String selectUrlByIds(String ossIds) { |
| | | List<String> list = new ArrayList<>(); |
| | | SysOssServiceImpl ossService = SpringUtils.getAopProxy(this); |
| | | for (Long id : StringUtils.splitTo(ossIds, Convert::toLong)) { |
| | | SysOssVo vo = SpringUtils.getAopProxy(this).getById(id); |
| | | SysOssVo vo = ossService.getById(id); |
| | | if (ObjectUtil.isNotNull(vo)) { |
| | | try { |
| | | list.add(this.matchingUrl(vo).getUrl()); |
| | |
| | | } |
| | | |
| | | /** |
| | | * éè¿é¨é¨IDæ¥è¯¢å²ä½ä½¿ç¨æ°é |
| | | * |
| | | * @param deptId é¨é¨id |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | public long countPostByDeptId(Long deptId) { |
| | | return baseMapper.selectCount(new LambdaQueryWrapper<SysPost>().eq(SysPost::getDeptId, deptId)); |
| | | } |
| | | |
| | | /** |
| | | * å é¤å²ä½ä¿¡æ¯ |
| | | * |
| | | * @param postId å²ä½ID |
| | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public int updateRole(SysRoleBo bo) { |
| | | SysRole role = MapstructUtils.convert(bo, SysRole.class); |
| | | |
| | | if (UserConstants.ROLE_DISABLE.equals(role.getStatus()) && this.countUserRoleByRoleId(role.getRoleId()) > 0) { |
| | | throw new ServiceException("è§è²å·²åé
ï¼ä¸è½ç¦ç¨!"); |
| | | } |
| | | // ä¿®æ¹è§è²ä¿¡æ¯ |
| | | baseMapper.updateById(role); |
| | | // å é¤è§è²ä¸èåå
³è |
| | |
| | | package org.dromara.system.service.impl; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | |
| | | } |
| | | |
| | | /** |
| | | * æ ¡éªå¥é¤åç§°æ¯å¦å¯ä¸ |
| | | */ |
| | | @Override |
| | | public boolean checkPackageNameUnique(SysTenantPackageBo bo) { |
| | | boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysTenantPackage>() |
| | | .eq(SysTenantPackage::getPackageName, bo.getPackageName()) |
| | | .ne(ObjectUtil.isNotNull(bo.getPackageId()), SysTenantPackage::getPackageId, bo.getPackageId())); |
| | | return !exist; |
| | | } |
| | | |
| | | /** |
| | | * ä¿®æ¹å¥é¤ç¶æ |
| | | * |
| | | * @param bo å¥é¤ä¿¡æ¯ |
| | |
| | | import org.dromara.common.mybatis.core.page.TableDataInfo; |
| | | import org.dromara.common.mybatis.helper.DataBaseHelper; |
| | | import org.dromara.common.satoken.utils.LoginHelper; |
| | | import org.dromara.system.domain.SysDept; |
| | | import org.dromara.system.domain.SysUser; |
| | | import org.dromara.system.domain.SysUserPost; |
| | | import org.dromara.system.domain.SysUserRole; |
| | | import org.dromara.system.domain.*; |
| | | import org.dromara.system.domain.bo.SysUserBo; |
| | | import org.dromara.system.domain.vo.SysPostVo; |
| | | import org.dromara.system.domain.vo.SysRoleVo; |
| | |
| | | */ |
| | | private void insertUserRole(Long userId, Long[] roleIds, boolean clear) { |
| | | if (ArrayUtil.isNotEmpty(roleIds)) { |
| | | // 夿æ¯å¦å
·ææ¤è§è²çæä½æé |
| | | List<SysRoleVo> roles = roleMapper.selectRoleList(new LambdaQueryWrapper<>()); |
| | | if (CollUtil.isEmpty(roles)) { |
| | | throw new ServiceException("没ææé访é®è§è²çæ°æ®"); |
| | | } |
| | | List<Long> roleList = StreamUtils.toList(roles, SysRoleVo::getRoleId); |
| | | List<Long> roleList = new ArrayList<>(List.of(roleIds)); |
| | | if (!LoginHelper.isSuperAdmin(userId)) { |
| | | roleList.remove(UserConstants.SUPER_ADMIN_ID); |
| | | } |
| | | List<Long> canDoRoleList = StreamUtils.filter(List.of(roleIds), roleList::contains); |
| | | if (CollUtil.isEmpty(canDoRoleList)) { |
| | | // 夿æ¯å¦å
·ææ¤è§è²çæä½æé |
| | | List<SysRoleVo> roles = roleMapper.selectRoleList( |
| | | new QueryWrapper<SysRole>().in("r.role_id", roleList)); |
| | | if (CollUtil.isEmpty(roles)) { |
| | | throw new ServiceException("没ææé访é®è§è²çæ°æ®"); |
| | | } |
| | | if (clear) { |
| | |
| | | userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId)); |
| | | } |
| | | // æ°å¢ç¨æ·ä¸è§è²ç®¡ç |
| | | List<SysUserRole> list = StreamUtils.toList(canDoRoleList, roleId -> { |
| | | List<SysUserRole> list = StreamUtils.toList(roleList, roleId -> { |
| | | SysUserRole ur = new SysUserRole(); |
| | | ur.setUserId(userId); |
| | | ur.setRoleId(roleId); |
| | |
| | | return List.of(); |
| | | } |
| | | List<SysUserVo> list = baseMapper.selectVoList(new LambdaQueryWrapper<SysUser>() |
| | | .select(SysUser::getUserId, SysUser::getUserName, SysUser::getNickName) |
| | | .select(SysUser::getUserId, SysUser::getUserName, SysUser::getNickName, SysUser::getEmail, SysUser::getPhonenumber) |
| | | .eq(SysUser::getStatus, UserConstants.USER_NORMAL) |
| | | .in(CollUtil.isNotEmpty(userIds), SysUser::getUserId, userIds)); |
| | | return BeanUtil.copyToList(list, UserDTO.class); |
| | |
| | | return StreamUtils.toList(userRoles, SysUserRole::getUserId); |
| | | } |
| | | |
| | | @Override |
| | | public List<UserDTO> selectUsersByRoleIds(List<Long> roleIds) { |
| | | if (CollUtil.isEmpty(roleIds)) { |
| | | return List.of(); |
| | | } |
| | | List<SysUserRole> userRoles = userRoleMapper.selectList( |
| | | new LambdaQueryWrapper<SysUserRole>().in(SysUserRole::getRoleId, roleIds)); |
| | | List<Long> userIds = StreamUtils.toList(userRoles, SysUserRole::getUserId); |
| | | return selectListByIds(userIds); |
| | | } |
| | | |
| | | @Override |
| | | public List<UserDTO> selectUsersByDeptIds(List<Long> deptIds) { |
| | | if (CollUtil.isEmpty(deptIds)) { |
| | | return List.of(); |
| | | } |
| | | List<SysUserVo> list = baseMapper.selectVoList(new LambdaQueryWrapper<SysUser>() |
| | | .select(SysUser::getUserId, SysUser::getUserName, SysUser::getNickName, SysUser::getEmail, SysUser::getPhonenumber) |
| | | .eq(SysUser::getStatus, UserConstants.USER_NORMAL) |
| | | .in(CollUtil.isNotEmpty(deptIds), SysUser::getDeptId, deptIds)); |
| | | return BeanUtil.copyToList(list, UserDTO.class); |
| | | } |
| | | } |
| | |
| | | <dependency> |
| | | <groupId>org.apache.xmlgraphics</groupId> |
| | | <artifactId>batik-all</artifactId> |
| | | <version>1.10</version> |
| | | <version>1.17</version> |
| | | <exclusions> |
| | | <exclusion> |
| | | <groupId>xalan</groupId> |
| | |
| | | import org.dromara.workflow.service.IActModelService; |
| | | import org.flowable.engine.RepositoryService; |
| | | import org.flowable.engine.repository.Model; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | |
| | | @RequestMapping("/workflow/model") |
| | | public class ActModelController extends BaseController { |
| | | |
| | | private final RepositoryService repositoryService; |
| | | |
| | | @Autowired(required = false) |
| | | private RepositoryService repositoryService; |
| | | private final IActModelService actModelService; |
| | | |
| | | |
| | |
| | | import org.dromara.workflow.service.IWfTaskBackNodeService; |
| | | import org.dromara.workflow.utils.QueryUtils; |
| | | import org.flowable.engine.TaskService; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | |
| | | @RequestMapping("/workflow/task") |
| | | public class ActTaskController extends BaseController { |
| | | |
| | | @Autowired(required = false) |
| | | private TaskService taskService; |
| | | private final IActTaskService actTaskService; |
| | | |
| | | private final TaskService taskService; |
| | | |
| | | private final IWfTaskBackNodeService wfTaskBackNodeService; |
| | | |
| | | |
| | |
| | | import org.flowable.engine.repository.ModelQuery; |
| | | import org.flowable.engine.repository.ProcessDefinition; |
| | | import org.flowable.validation.ValidationError; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | |
| | | @Service |
| | | public class ActModelServiceImpl implements IActModelService { |
| | | |
| | | private final RepositoryService repositoryService; |
| | | @Autowired(required = false) |
| | | private RepositoryService repositoryService; |
| | | private final IWfNodeConfigService wfNodeConfigService; |
| | | private final IWfDefinitionConfigService wfDefinitionConfigService; |
| | | |
| | |
| | | import org.flowable.engine.history.HistoricProcessInstance; |
| | | import org.flowable.engine.impl.bpmn.deployer.ResourceNameUtil; |
| | | import org.flowable.engine.repository.*; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | |
| | | @Service |
| | | public class ActProcessDefinitionServiceImpl implements IActProcessDefinitionService { |
| | | |
| | | private final RepositoryService repositoryService; |
| | | private final ProcessMigrationService processMigrationService; |
| | | @Autowired(required = false) |
| | | private RepositoryService repositoryService; |
| | | @Autowired(required = false) |
| | | private ProcessMigrationService processMigrationService; |
| | | private final IWfCategoryService wfCategoryService; |
| | | private final IWfDefinitionConfigService wfDefinitionConfigService; |
| | | private final WfDefinitionConfigMapper wfDefinitionConfigMapper; |
| | |
| | | Model modelData = repositoryService.newModel(); |
| | | modelData.setKey(pd.getKey()); |
| | | modelData.setName(pd.getName()); |
| | | modelData.setCategory(pd.getCategory()); |
| | | modelData.setTenantId(pd.getTenantId()); |
| | | repositoryService.saveModel(modelData); |
| | | repositoryService.addModelEditorSource(modelData.getId(), IoUtil.readBytes(inputStream)); |
| | |
| | | initWfDefConfig(); |
| | | } else { |
| | | String originalFilename = file.getOriginalFilename(); |
| | | String bpmnResourceSuffix = ResourceNameUtil.BPMN_RESOURCE_SUFFIXES[0]; |
| | | if (originalFilename.contains(bpmnResourceSuffix)) { |
| | | if (StringUtils.containsAny(originalFilename, ResourceNameUtil.BPMN_RESOURCE_SUFFIXES)) { |
| | | // æä»¶å = æµç¨åç§°-æµç¨key |
| | | String[] splitFilename = originalFilename.substring(0, originalFilename.lastIndexOf(".")).split("-"); |
| | | if (splitFilename.length < 2) { |
| | |
| | | import org.flowable.task.api.Task; |
| | | import org.flowable.task.api.history.HistoricTaskInstance; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | |
| | | @Service |
| | | public class ActProcessInstanceServiceImpl implements IActProcessInstanceService { |
| | | |
| | | private final RepositoryService repositoryService; |
| | | private final RuntimeService runtimeService; |
| | | private final HistoryService historyService; |
| | | private final TaskService taskService; |
| | | @Autowired(required = false) |
| | | private RepositoryService repositoryService; |
| | | @Autowired(required = false) |
| | | private RuntimeService runtimeService; |
| | | @Autowired(required = false) |
| | | private HistoryService historyService; |
| | | @Autowired(required = false) |
| | | private TaskService taskService; |
| | | @Autowired(required = false) |
| | | private ManagementService managementService; |
| | | private final IActHiProcinstService actHiProcinstService; |
| | | private final ManagementService managementService; |
| | | private final IWfTaskBackNodeService wfTaskBackNodeService; |
| | | private final IWfNodeConfigService wfNodeConfigService; |
| | | private final FlowProcessEventHandler flowProcessEventHandler; |
| | |
| | | import org.flowable.task.api.history.HistoricTaskInstance; |
| | | import org.flowable.task.service.impl.persistence.entity.TaskEntity; |
| | | import org.flowable.variable.api.persistence.entity.VariableInstance; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.scheduling.annotation.Async; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | |
| | | @Service |
| | | public class ActTaskServiceImpl implements IActTaskService { |
| | | |
| | | private final RuntimeService runtimeService; |
| | | private final TaskService taskService; |
| | | private final HistoryService historyService; |
| | | private final IdentityService identityService; |
| | | private final ManagementService managementService; |
| | | @Autowired(required = false) |
| | | private RuntimeService runtimeService; |
| | | @Autowired(required = false) |
| | | private TaskService taskService; |
| | | @Autowired(required = false) |
| | | private HistoryService historyService; |
| | | @Autowired(required = false) |
| | | private IdentityService identityService; |
| | | @Autowired(required = false) |
| | | private ManagementService managementService; |
| | | private final ActTaskMapper actTaskMapper; |
| | | private final IWfTaskBackNodeService wfTaskBackNodeService; |
| | | private final ActHiTaskinstMapper actHiTaskinstMapper; |
| | |
| | | queryWrapper.eq("t.business_status_", BusinessStatusEnum.WAITING.getStatus()); |
| | | queryWrapper.eq(TenantHelper.isEnable(), "t.tenant_id_", TenantHelper.getTenantId()); |
| | | String ids = StreamUtils.join(roleIds, x -> "'" + x + "'"); |
| | | queryWrapper.and(w1 -> w1.eq("t.assignee_", userId).or(w2 -> w2.isNull("t.assignee_").apply("exists ( select LINK.ID_ from ACT_RU_IDENTITYLINK LINK where LINK.TASK_ID_ = t.ID_ and LINK.TYPE_ = 'candidate' and (LINK.USER_ID_ = {0} or ( LINK.GROUP_ID_ IN ({1}) ) ))", userId, ids))); |
| | | queryWrapper.and(w1 -> w1.eq("t.assignee_", userId).or(w2 -> w2.isNull("t.assignee_").apply("exists ( select LINK.ID_ from ACT_RU_IDENTITYLINK LINK where LINK.TASK_ID_ = t.ID_ and LINK.TYPE_ = 'candidate' and (LINK.USER_ID_ = {0} or ( LINK.GROUP_ID_ IN (" + ids + ") ) ))", userId))); |
| | | if (StringUtils.isNotBlank(taskBo.getName())) { |
| | | queryWrapper.like("t.name_", taskBo.getName()); |
| | | } |
| | |
| | | import org.flowable.engine.repository.Deployment; |
| | | import org.flowable.engine.repository.Model; |
| | | import org.flowable.engine.repository.ProcessDefinition; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | |
| | | public class WfCategoryServiceImpl implements IWfCategoryService { |
| | | |
| | | private final WfCategoryMapper baseMapper; |
| | | |
| | | private final RepositoryService repositoryService; |
| | | @Autowired(required = false) |
| | | private RepositoryService repositoryService; |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨åç±» |
| | |
| | | import org.dromara.workflow.service.IActProcessInstanceService; |
| | | import org.dromara.workflow.utils.WorkflowUtils; |
| | | import org.flowable.engine.RuntimeService; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.List; |
| | |
| | | @Service |
| | | public class WorkflowServiceImpl implements WorkflowService { |
| | | |
| | | @Autowired(required = false) |
| | | private RuntimeService runtimeService; |
| | | private final IActProcessInstanceService iActProcessInstanceService; |
| | | private final RuntimeService runtimeService; |
| | | private final IActHiProcinstService iActHiProcinstService; |
| | | /** |
| | | * è¿è¡ä¸çå®ä¾ å é¤ç¨å®ä¾ï¼å é¤åå²è®°å½ï¼å é¤ä¸å¡ä¸æµç¨å
³èä¿¡æ¯ |
| | |
| | | network_mode: "host" |
| | | |
| | | ruoyi-server1: |
| | | image: ruoyi/ruoyi-server:5.2.1 |
| | | image: ruoyi/ruoyi-server:5.2.2 |
| | | container_name: ruoyi-server1 |
| | | environment: |
| | | # æ¶åºä¸æµ· |
| | |
| | | network_mode: "host" |
| | | |
| | | ruoyi-server2: |
| | | image: ruoyi/ruoyi-server:5.2.1 |
| | | image: ruoyi/ruoyi-server:5.2.2 |
| | | container_name: ruoyi-server2 |
| | | environment: |
| | | # æ¶åºä¸æµ· |
| | |
| | | network_mode: "host" |
| | | |
| | | ruoyi-monitor-admin: |
| | | image: ruoyi/ruoyi-monitor-admin:5.2.1 |
| | | image: ruoyi/ruoyi-monitor-admin:5.2.2 |
| | | container_name: ruoyi-monitor-admin |
| | | environment: |
| | | # æ¶åºä¸æµ· |
| | |
| | | network_mode: "host" |
| | | |
| | | ruoyi-snailjob-server: |
| | | image: ruoyi/ruoyi-snailjob-server:5.2.1 |
| | | image: ruoyi/ruoyi-snailjob-server:5.2.2 |
| | | container_name: ruoyi-snailjob-server |
| | | environment: |
| | | # æ¶åºä¸æµ· |
| | |
| | | proxy_set_header X-Real-IP $remote_addr; |
| | | proxy_set_header REMOTE-HOST $remote_addr; |
| | | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; |
| | | # websocketåæ° |
| | | proxy_read_timeout 86400s; |
| | | # sse ä¸ websocketåæ° |
| | | proxy_http_version 1.1; |
| | | proxy_set_header Upgrade $http_upgrade; |
| | | proxy_set_header Connection "upgrade"; |
| | | proxy_buffering off; |
| | | proxy_cache off; |
| | | proxy_pass http://server/; |
| | | } |
| | | |
| | |
| | | SnailJob Database Transfer Tool |
| | | Source Server Type : MySQL |
| | | Target Server Type : Oracle |
| | | Date: 2024-05-14 23:36:38 |
| | | Date: 2024-07-06 12:49:36 |
| | | */ |
| | | |
| | | |
| | |
| | | COMMENT ON COLUMN sj_notify_recipient.id IS '主é®'; |
| | | COMMENT ON COLUMN sj_notify_recipient.namespace_id IS 'å½å空é´id'; |
| | | COMMENT ON COLUMN sj_notify_recipient.recipient_name IS 'æ¥æ¶äººåç§°'; |
| | | COMMENT ON COLUMN sj_notify_recipient.notify_type IS 'éç¥ç±»å 1ãéé 2ãé®ä»¶ 3ãä¼ä¸å¾®ä¿¡ 4 é£ä¹¦'; |
| | | COMMENT ON COLUMN sj_notify_recipient.notify_type IS 'éç¥ç±»å 1ãéé 2ãé®ä»¶ 3ãä¼ä¸å¾®ä¿¡ 4 é£ä¹¦ 5 webhook'; |
| | | COMMENT ON COLUMN sj_notify_recipient.notify_attribute IS 'é
ç½®å±æ§'; |
| | | COMMENT ON COLUMN sj_notify_recipient.description IS 'æè¿°'; |
| | | COMMENT ON COLUMN sj_notify_recipient.create_dt IS 'å建æ¶é´'; |
| | |
| | | ALTER TABLE sj_retry_task_log_message |
| | | ADD CONSTRAINT pk_sj_retry_task_log_message PRIMARY KEY (id); |
| | | |
| | | CREATE INDEX idx_sj_retry_task_log_message_01 ON sj_retry_task_log_message (namespace_id, group_name, unique_id); |
| | | CREATE INDEX idx_sj_retry_task_log_message_02 ON sj_retry_task_log_message (create_dt); |
| | | CREATE INDEX idx_sj_rt_log_message_01 ON sj_retry_task_log_message (namespace_id, group_name, unique_id); |
| | | CREATE INDEX idx_sj_rt_log_message_02 ON sj_retry_task_log_message (create_dt); |
| | | |
| | | COMMENT ON COLUMN sj_retry_task_log_message.id IS '主é®'; |
| | | COMMENT ON COLUMN sj_retry_task_log_message.namespace_id IS 'å½å空é´id'; |
| | |
| | | -- sj_distributed_lock |
| | | CREATE TABLE sj_distributed_lock |
| | | ( |
| | | id number GENERATED ALWAYS AS IDENTITY, |
| | | name varchar2(64) NULL, |
| | | name varchar2(64) NOT NULL, |
| | | lock_until timestamp(3) DEFAULT CURRENT_TIMESTAMP(3) NOT NULL, |
| | | locked_at timestamp(3) DEFAULT CURRENT_TIMESTAMP(3) NOT NULL, |
| | | locked_by varchar2(255) NULL, |
| | |
| | | ); |
| | | |
| | | ALTER TABLE sj_distributed_lock |
| | | ADD CONSTRAINT pk_sj_distributed_lock PRIMARY KEY (id); |
| | | ADD CONSTRAINT pk_sj_distributed_lock PRIMARY KEY (name); |
| | | |
| | | COMMENT ON COLUMN sj_distributed_lock.id IS '主é®'; |
| | | COMMENT ON COLUMN sj_distributed_lock.name IS 'éåç§°'; |
| | | COMMENT ON COLUMN sj_distributed_lock.lock_until IS 'é宿¶é¿'; |
| | | COMMENT ON COLUMN sj_distributed_lock.locked_at IS 'é宿¶é´'; |
| | |
| | | ALTER TABLE sj_system_user_permission |
| | | ADD CONSTRAINT pk_sj_system_user_permission PRIMARY KEY (id); |
| | | |
| | | CREATE UNIQUE INDEX uk_sj_system_user_permission_01 ON sj_system_user_permission (namespace_id, group_name, system_user_id); |
| | | CREATE UNIQUE INDEX uk_sj_su_permission_01 ON sj_system_user_permission (namespace_id, group_name, system_user_id); |
| | | |
| | | COMMENT ON COLUMN sj_system_user_permission.id IS '主é®'; |
| | | COMMENT ON COLUMN sj_system_user_permission.group_name IS 'ç»åç§°'; |
| | |
| | | parent_id number DEFAULT 0 NOT NULL, |
| | | task_status smallint DEFAULT 0 NOT NULL, |
| | | retry_count number DEFAULT 0 NOT NULL, |
| | | mr_stage smallint DEFAULT NULL NULL, |
| | | leaf smallint DEFAULT '1' NOT NULL, |
| | | task_name varchar2(255) DEFAULT '' NULL, |
| | | client_info varchar2(128) DEFAULT NULL NULL, |
| | | wf_context clob DEFAULT NULL NULL, |
| | | result_message clob NULL, |
| | | args_str clob DEFAULT NULL NULL, |
| | | args_type smallint DEFAULT 1 NOT NULL, |
| | |
| | | COMMENT ON COLUMN sj_job_task.parent_id IS 'ç¶æ§è¡å¨id'; |
| | | COMMENT ON COLUMN sj_job_task.task_status IS 'æ§è¡çç¶æ 0ã失败 1ãæå'; |
| | | COMMENT ON COLUMN sj_job_task.retry_count IS 'éè¯æ¬¡æ°'; |
| | | COMMENT ON COLUMN sj_job_task.mr_stage IS '卿åçæå¤é¶æ®µ 1:map 2:reduce 3:mergeReduce'; |
| | | COMMENT ON COLUMN sj_job_task.leaf IS 'å¶åèç¹'; |
| | | COMMENT ON COLUMN sj_job_task.task_name IS 'ä»»å¡åç§°'; |
| | | COMMENT ON COLUMN sj_job_task.client_info IS '客æ·ç«¯å°å clientId#ip:port'; |
| | | COMMENT ON COLUMN sj_job_task.wf_context IS '工使µå
¨å±ä¸ä¸æ'; |
| | | COMMENT ON COLUMN sj_job_task.result_message IS 'æ§è¡ç»æ'; |
| | | COMMENT ON COLUMN sj_job_task.args_str IS 'æ§è¡æ¹æ³åæ°'; |
| | | COMMENT ON COLUMN sj_job_task.args_type IS 'åæ°ç±»å '; |
| | |
| | | executor_timeout number DEFAULT 0 NOT NULL, |
| | | description varchar2(256) DEFAULT '' NULL, |
| | | flow_info clob DEFAULT NULL NULL, |
| | | wf_context clob DEFAULT NULL NULL, |
| | | bucket_index number DEFAULT 0 NOT NULL, |
| | | version number NOT NULL, |
| | | ext_attrs varchar2(256) DEFAULT '' NULL, |
| | |
| | | COMMENT ON COLUMN sj_workflow.executor_timeout IS '任塿§è¡è¶
æ¶æ¶é´ï¼åä½ç§'; |
| | | COMMENT ON COLUMN sj_workflow.description IS 'æè¿°'; |
| | | COMMENT ON COLUMN sj_workflow.flow_info IS 'æµç¨ä¿¡æ¯'; |
| | | COMMENT ON COLUMN sj_workflow.wf_context IS 'ä¸ä¸æ'; |
| | | COMMENT ON COLUMN sj_workflow.bucket_index IS 'bucket'; |
| | | COMMENT ON COLUMN sj_workflow.version IS 'çæ¬å·'; |
| | | COMMENT ON COLUMN sj_workflow.ext_attrs IS 'æ©å±å段'; |
| | |
| | | task_batch_status smallint DEFAULT 0 NOT NULL, |
| | | operation_reason smallint DEFAULT 0 NOT NULL, |
| | | flow_info clob DEFAULT NULL NULL, |
| | | wf_context clob DEFAULT NULL NULL, |
| | | execution_at number DEFAULT 0 NOT NULL, |
| | | ext_attrs varchar2(256) DEFAULT '' NULL, |
| | | version number DEFAULT 1 NOT NULL, |
| | | deleted smallint DEFAULT 0 NOT NULL, |
| | | create_dt date DEFAULT CURRENT_TIMESTAMP NOT NULL, |
| | | update_dt date DEFAULT CURRENT_TIMESTAMP NOT NULL |
| | |
| | | COMMENT ON COLUMN sj_workflow_task_batch.task_batch_status IS '任塿¹æ¬¡ç¶æ 0ã失败 1ãæå'; |
| | | COMMENT ON COLUMN sj_workflow_task_batch.operation_reason IS 'æä½åå '; |
| | | COMMENT ON COLUMN sj_workflow_task_batch.flow_info IS 'æµç¨ä¿¡æ¯'; |
| | | COMMENT ON COLUMN sj_workflow_task_batch.wf_context IS 'å
¨å±ä¸ä¸æ'; |
| | | COMMENT ON COLUMN sj_workflow_task_batch.execution_at IS '任塿§è¡æ¶é´'; |
| | | COMMENT ON COLUMN sj_workflow_task_batch.ext_attrs IS 'æ©å±å段'; |
| | | COMMENT ON COLUMN sj_workflow_task_batch.version IS 'çæ¬å·'; |
| | | COMMENT ON COLUMN sj_workflow_task_batch.deleted IS 'é»è¾å é¤ 1ãå é¤'; |
| | | COMMENT ON COLUMN sj_workflow_task_batch.create_dt IS 'å建æ¶é´'; |
| | | COMMENT ON COLUMN sj_workflow_task_batch.update_dt IS 'ä¿®æ¹æ¶é´'; |
| | | COMMENT ON TABLE sj_workflow_task_batch IS '工使µæ¹æ¬¡'; |
| | | |
| | |
| | | SnailJob Database Transfer Tool |
| | | Source Server Type : MySQL |
| | | Target Server Type : PostgreSQL |
| | | Date: 2024-05-13 22:49:34 |
| | | Date: 2024-07-06 11:45:40 |
| | | */ |
| | | |
| | | |
| | |
| | | COMMENT ON COLUMN sj_notify_recipient.id IS '主é®'; |
| | | COMMENT ON COLUMN sj_notify_recipient.namespace_id IS 'å½å空é´id'; |
| | | COMMENT ON COLUMN sj_notify_recipient.recipient_name IS 'æ¥æ¶äººåç§°'; |
| | | COMMENT ON COLUMN sj_notify_recipient.notify_type IS 'éç¥ç±»å 1ãéé 2ãé®ä»¶ 3ãä¼ä¸å¾®ä¿¡ 4 é£ä¹¦'; |
| | | COMMENT ON COLUMN sj_notify_recipient.notify_type IS 'éç¥ç±»å 1ãéé 2ãé®ä»¶ 3ãä¼ä¸å¾®ä¿¡ 4 é£ä¹¦ 5 webhook'; |
| | | COMMENT ON COLUMN sj_notify_recipient.notify_attribute IS 'é
ç½®å±æ§'; |
| | | COMMENT ON COLUMN sj_notify_recipient.description IS 'æè¿°'; |
| | | COMMENT ON COLUMN sj_notify_recipient.create_dt IS 'å建æ¶é´'; |
| | |
| | | -- sj_distributed_lock |
| | | CREATE TABLE sj_distributed_lock |
| | | ( |
| | | id bigserial PRIMARY KEY, |
| | | name varchar(64) NOT NULL, |
| | | name varchar(64) PRIMARY KEY, |
| | | lock_until timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), |
| | | locked_at timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), |
| | | locked_by varchar(255) NOT NULL, |
| | |
| | | update_dt timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP |
| | | ); |
| | | |
| | | COMMENT ON COLUMN sj_distributed_lock.id IS '主é®'; |
| | | COMMENT ON COLUMN sj_distributed_lock.name IS 'éåç§°'; |
| | | COMMENT ON COLUMN sj_distributed_lock.lock_until IS 'é宿¶é¿'; |
| | | COMMENT ON COLUMN sj_distributed_lock.locked_at IS 'é宿¶é´'; |
| | |
| | | parent_id bigint NOT NULL DEFAULT 0, |
| | | task_status smallint NOT NULL DEFAULT 0, |
| | | retry_count int NOT NULL DEFAULT 0, |
| | | mr_stage smallint NULL DEFAULT NULL, |
| | | leaf smallint NOT NULL DEFAULT '1', |
| | | task_name varchar(255) NOT NULL DEFAULT '', |
| | | client_info varchar(128) NULL DEFAULT NULL, |
| | | wf_context text NULL DEFAULT NULL, |
| | | result_message text NOT NULL, |
| | | args_str text NULL DEFAULT NULL, |
| | | args_type smallint NOT NULL DEFAULT 1, |
| | |
| | | COMMENT ON COLUMN sj_job_task.parent_id IS 'ç¶æ§è¡å¨id'; |
| | | COMMENT ON COLUMN sj_job_task.task_status IS 'æ§è¡çç¶æ 0ã失败 1ãæå'; |
| | | COMMENT ON COLUMN sj_job_task.retry_count IS 'éè¯æ¬¡æ°'; |
| | | COMMENT ON COLUMN sj_job_task.mr_stage IS '卿åçæå¤é¶æ®µ 1:map 2:reduce 3:mergeReduce'; |
| | | COMMENT ON COLUMN sj_job_task.leaf IS 'å¶åèç¹'; |
| | | COMMENT ON COLUMN sj_job_task.task_name IS 'ä»»å¡åç§°'; |
| | | COMMENT ON COLUMN sj_job_task.client_info IS '客æ·ç«¯å°å clientId#ip:port'; |
| | | COMMENT ON COLUMN sj_job_task.wf_context IS '工使µå
¨å±ä¸ä¸æ'; |
| | | COMMENT ON COLUMN sj_job_task.result_message IS 'æ§è¡ç»æ'; |
| | | COMMENT ON COLUMN sj_job_task.args_str IS 'æ§è¡æ¹æ³åæ°'; |
| | | COMMENT ON COLUMN sj_job_task.args_type IS 'åæ°ç±»å '; |
| | |
| | | executor_timeout int NOT NULL DEFAULT 0, |
| | | description varchar(256) NOT NULL DEFAULT '', |
| | | flow_info text NULL DEFAULT NULL, |
| | | wf_context text NULL DEFAULT NULL, |
| | | bucket_index int NOT NULL DEFAULT 0, |
| | | version int NOT NULL, |
| | | ext_attrs varchar(256) NULL DEFAULT '', |
| | |
| | | COMMENT ON COLUMN sj_workflow.executor_timeout IS '任塿§è¡è¶
æ¶æ¶é´ï¼åä½ç§'; |
| | | COMMENT ON COLUMN sj_workflow.description IS 'æè¿°'; |
| | | COMMENT ON COLUMN sj_workflow.flow_info IS 'æµç¨ä¿¡æ¯'; |
| | | COMMENT ON COLUMN sj_workflow.wf_context IS 'ä¸ä¸æ'; |
| | | COMMENT ON COLUMN sj_workflow.bucket_index IS 'bucket'; |
| | | COMMENT ON COLUMN sj_workflow.version IS 'çæ¬å·'; |
| | | COMMENT ON COLUMN sj_workflow.ext_attrs IS 'æ©å±å段'; |
| | |
| | | task_batch_status smallint NOT NULL DEFAULT 0, |
| | | operation_reason smallint NOT NULL DEFAULT 0, |
| | | flow_info text NULL DEFAULT NULL, |
| | | wf_context text NULL DEFAULT NULL, |
| | | execution_at bigint NOT NULL DEFAULT 0, |
| | | ext_attrs varchar(256) NULL DEFAULT '', |
| | | version int NOT NULL DEFAULT 1, |
| | | deleted smallint NOT NULL DEFAULT 0, |
| | | create_dt timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| | | update_dt timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP |
| | |
| | | COMMENT ON COLUMN sj_workflow_task_batch.task_batch_status IS '任塿¹æ¬¡ç¶æ 0ã失败 1ãæå'; |
| | | COMMENT ON COLUMN sj_workflow_task_batch.operation_reason IS 'æä½åå '; |
| | | COMMENT ON COLUMN sj_workflow_task_batch.flow_info IS 'æµç¨ä¿¡æ¯'; |
| | | COMMENT ON COLUMN sj_workflow_task_batch.wf_context IS 'å
¨å±ä¸ä¸æ'; |
| | | COMMENT ON COLUMN sj_workflow_task_batch.execution_at IS '任塿§è¡æ¶é´'; |
| | | COMMENT ON COLUMN sj_workflow_task_batch.ext_attrs IS 'æ©å±å段'; |
| | | COMMENT ON COLUMN sj_workflow_task_batch.version IS 'çæ¬å·'; |
| | | COMMENT ON COLUMN sj_workflow_task_batch.deleted IS 'é»è¾å é¤ 1ãå é¤'; |
| | | COMMENT ON COLUMN sj_workflow_task_batch.create_dt IS 'å建æ¶é´'; |
| | | COMMENT ON COLUMN sj_workflow_task_batch.update_dt IS 'ä¿®æ¹æ¶é´'; |
| | | COMMENT ON TABLE sj_workflow_task_batch IS '工使µæ¹æ¬¡'; |
| | | |
| | |
| | | `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主é®', |
| | | `namespace_id` varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT 'å½å空é´id', |
| | | `recipient_name` varchar(64) NOT NULL COMMENT 'æ¥æ¶äººåç§°', |
| | | `notify_type` tinyint(4) NOT NULL DEFAULT 0 COMMENT 'éç¥ç±»å 1ãéé 2ãé®ä»¶ 3ãä¼ä¸å¾®ä¿¡ 4 é£ä¹¦', |
| | | `notify_type` tinyint(4) NOT NULL DEFAULT 0 COMMENT 'éç¥ç±»å 1ãéé 2ãé®ä»¶ 3ãä¼ä¸å¾®ä¿¡ 4 é£ä¹¦ 5 webhook', |
| | | `notify_attribute` varchar(512) NOT NULL COMMENT 'é
ç½®å±æ§', |
| | | `description` varchar(256) NOT NULL DEFAULT '' COMMENT 'æè¿°', |
| | | `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'å建æ¶é´', |
| | |
| | | |
| | | CREATE TABLE `sj_distributed_lock` |
| | | ( |
| | | `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主é®', |
| | | `name` varchar(64) NOT NULL COMMENT 'éåç§°', |
| | | `lock_until` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT 'é宿¶é¿', |
| | | `locked_at` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'é宿¶é´', |
| | | `locked_by` varchar(255) NOT NULL COMMENT 'éå®è
', |
| | | `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'å建æ¶é´', |
| | | `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'ä¿®æ¹æ¶é´', |
| | | PRIMARY KEY (`id`), |
| | | UNIQUE KEY `uk_name` (`name`) |
| | | PRIMARY KEY (`name`) |
| | | ) ENGINE = InnoDB |
| | | AUTO_INCREMENT = 0 |
| | | DEFAULT CHARSET = utf8mb4 COMMENT ='éå®è¡¨'; |
| | |
| | | `job_id` bigint(20) NOT NULL COMMENT 'ä»»å¡ä¿¡æ¯id', |
| | | `task_batch_id` bigint(20) NOT NULL COMMENT 'è°åº¦ä»»å¡id', |
| | | `parent_id` bigint(20) NOT NULL DEFAULT 0 COMMENT 'ç¶æ§è¡å¨id', |
| | | `task_status` tinyint(4) NOT NULL DEFAULT 0 COMMENT 'æ§è¡çç¶æ 0ã失败 1ãæå', |
| | | `task_status` tinyint NOT NULL DEFAULT 0 COMMENT 'æ§è¡çç¶æ 0ã失败 1ãæå', |
| | | `retry_count` int(11) NOT NULL DEFAULT 0 COMMENT 'éè¯æ¬¡æ°', |
| | | `mr_stage` tinyint DEFAULT NULL COMMENT '卿åçæå¤é¶æ®µ 1:map 2:reduce 3:mergeReduce', |
| | | `leaf` tinyint NOT NULL DEFAULT '1' COMMENT 'å¶åèç¹', |
| | | `task_name` varchar(255) NOT NULL DEFAULT '' COMMENT 'ä»»å¡åç§°', |
| | | `client_info` varchar(128) DEFAULT NULL COMMENT '客æ·ç«¯å°å clientId#ip:port', |
| | | `wf_context` text DEFAULT NULL COMMENT '工使µå
¨å±ä¸ä¸æ', |
| | | `result_message` text NOT NULL COMMENT 'æ§è¡ç»æ', |
| | | `args_str` text DEFAULT NULL COMMENT 'æ§è¡æ¹æ³åæ°', |
| | | `args_type` tinyint(4) NOT NULL DEFAULT 1 COMMENT 'åæ°ç±»å ', |
| | | `args_type` tinyint NOT NULL DEFAULT 1 COMMENT 'åæ°ç±»å ', |
| | | `ext_attrs` varchar(256) NULL DEFAULT '' COMMENT 'æ©å±å段', |
| | | `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'å建æ¶é´', |
| | | `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'ä¿®æ¹æ¶é´', |
| | |
| | | `executor_timeout` int(11) NOT NULL DEFAULT 0 COMMENT '任塿§è¡è¶
æ¶æ¶é´ï¼åä½ç§', |
| | | `description` varchar(256) NOT NULL DEFAULT '' COMMENT 'æè¿°', |
| | | `flow_info` text DEFAULT NULL COMMENT 'æµç¨ä¿¡æ¯', |
| | | `wf_context` text DEFAULT NULL COMMENT 'ä¸ä¸æ', |
| | | `bucket_index` int(11) NOT NULL DEFAULT 0 COMMENT 'bucket', |
| | | `version` int(11) NOT NULL COMMENT 'çæ¬å·', |
| | | `ext_attrs` varchar(256) NULL DEFAULT '' COMMENT 'æ©å±å段', |
| | |
| | | `task_batch_status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '任塿¹æ¬¡ç¶æ 0ã失败 1ãæå', |
| | | `operation_reason` tinyint(4) NOT NULL DEFAULT 0 COMMENT 'æä½åå ', |
| | | `flow_info` text DEFAULT NULL COMMENT 'æµç¨ä¿¡æ¯', |
| | | `wf_context` text DEFAULT NULL COMMENT 'å
¨å±ä¸ä¸æ', |
| | | `execution_at` bigint(13) NOT NULL DEFAULT 0 COMMENT '任塿§è¡æ¶é´', |
| | | `ext_attrs` varchar(256) NULL DEFAULT '' COMMENT 'æ©å±å段', |
| | | `version` int(11) NOT NULL DEFAULT 1 COMMENT 'çæ¬å·', |
| | | `deleted` tinyint(4) NOT NULL DEFAULT 0 COMMENT 'é»è¾å é¤ 1ãå é¤', |
| | | `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'å建æ¶é´', |
| | | `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'ä¿®æ¹æ¶é´', |
| | |
| | | SnailJob Database Transfer Tool |
| | | Source Server Type : MySQL |
| | | Target Server Type : Microsoft SQL Server |
| | | Date: 2024-05-13 23:03:34 |
| | | Date: 2024-07-06 12:55:47 |
| | | */ |
| | | |
| | | |
| | |
| | | GO |
| | | |
| | | EXEC sp_addextendedproperty |
| | | 'MS_Description', N'éç¥ç±»å 1ãéé 2ãé®ä»¶ 3ãä¼ä¸å¾®ä¿¡ 4 é£ä¹¦', |
| | | 'MS_Description', N'éç¥ç±»å 1ãéé 2ãé®ä»¶ 3ãä¼ä¸å¾®ä¿¡ 4 é£ä¹¦ 5 webhook', |
| | | 'SCHEMA', N'dbo', |
| | | 'TABLE', N'sj_notify_recipient', |
| | | 'COLUMN', N'notify_type' |
| | |
| | | -- sj_distributed_lock |
| | | CREATE TABLE sj_distributed_lock |
| | | ( |
| | | id bigint NOT NULL PRIMARY KEY IDENTITY, |
| | | name nvarchar(64) NOT NULL, |
| | | name nvarchar(64) NOT NULL PRIMARY KEY, |
| | | lock_until datetime2 NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| | | locked_at datetime2 NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| | | locked_by nvarchar(255) NOT NULL, |
| | | create_dt datetime2 NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| | | update_dt datetime2 NOT NULL DEFAULT CURRENT_TIMESTAMP |
| | | ) |
| | | GO |
| | | |
| | | EXEC sp_addextendedproperty |
| | | 'MS_Description', N'主é®', |
| | | 'SCHEMA', N'dbo', |
| | | 'TABLE', N'sj_distributed_lock', |
| | | 'COLUMN', N'id' |
| | | GO |
| | | |
| | | EXEC sp_addextendedproperty |
| | |
| | | parent_id bigint NOT NULL DEFAULT 0, |
| | | task_status tinyint NOT NULL DEFAULT 0, |
| | | retry_count int NOT NULL DEFAULT 0, |
| | | mr_stage tinyint NULL DEFAULT NULL, |
| | | leaf tinyint NOT NULL DEFAULT '1', |
| | | task_name nvarchar(255) NOT NULL DEFAULT '', |
| | | client_info nvarchar(128) NULL DEFAULT NULL, |
| | | wf_context nvarchar(max) NULL DEFAULT NULL, |
| | | result_message nvarchar(max) NOT NULL, |
| | | args_str nvarchar(max) NULL DEFAULT NULL, |
| | | args_type tinyint NOT NULL DEFAULT 1, |
| | |
| | | GO |
| | | |
| | | EXEC sp_addextendedproperty |
| | | 'MS_Description', N'卿åçæå¤é¶æ®µ 1:map 2:reduce 3:mergeReduce', |
| | | 'SCHEMA', N'dbo', |
| | | 'TABLE', N'sj_job_task', |
| | | 'COLUMN', N'mr_stage' |
| | | GO |
| | | |
| | | EXEC sp_addextendedproperty |
| | | 'MS_Description', N'å¶åèç¹', |
| | | 'SCHEMA', N'dbo', |
| | | 'TABLE', N'sj_job_task', |
| | | 'COLUMN', N'leaf' |
| | | GO |
| | | |
| | | EXEC sp_addextendedproperty |
| | | 'MS_Description', N'ä»»å¡åç§°', |
| | | 'SCHEMA', N'dbo', |
| | | 'TABLE', N'sj_job_task', |
| | | 'COLUMN', N'task_name' |
| | | GO |
| | | |
| | | EXEC sp_addextendedproperty |
| | | 'MS_Description', N'客æ·ç«¯å°å clientId#ip:port', |
| | | 'SCHEMA', N'dbo', |
| | | 'TABLE', N'sj_job_task', |
| | | 'COLUMN', N'client_info' |
| | | GO |
| | | |
| | | EXEC sp_addextendedproperty |
| | | 'MS_Description', N'工使µå
¨å±ä¸ä¸æ', |
| | | 'SCHEMA', N'dbo', |
| | | 'TABLE', N'sj_job_task', |
| | | 'COLUMN', N'wf_context' |
| | | GO |
| | | |
| | | EXEC sp_addextendedproperty |
| | |
| | | executor_timeout int NOT NULL DEFAULT 0, |
| | | description nvarchar(256) NOT NULL DEFAULT '', |
| | | flow_info nvarchar(max) NULL DEFAULT NULL, |
| | | wf_context nvarchar(max) NULL DEFAULT NULL, |
| | | bucket_index int NOT NULL DEFAULT 0, |
| | | version int NOT NULL, |
| | | ext_attrs nvarchar(256) NULL DEFAULT '', |
| | |
| | | 'SCHEMA', N'dbo', |
| | | 'TABLE', N'sj_workflow', |
| | | 'COLUMN', N'flow_info' |
| | | GO |
| | | |
| | | EXEC sp_addextendedproperty |
| | | 'MS_Description', N'ä¸ä¸æ', |
| | | 'SCHEMA', N'dbo', |
| | | 'TABLE', N'sj_workflow', |
| | | 'COLUMN', N'wf_context' |
| | | GO |
| | | |
| | | EXEC sp_addextendedproperty |
| | |
| | | task_batch_status tinyint NOT NULL DEFAULT 0, |
| | | operation_reason tinyint NOT NULL DEFAULT 0, |
| | | flow_info nvarchar(max) NULL DEFAULT NULL, |
| | | wf_context nvarchar(max) NULL DEFAULT NULL, |
| | | execution_at bigint NOT NULL DEFAULT 0, |
| | | ext_attrs nvarchar(256) NULL DEFAULT '', |
| | | version int NOT NULL DEFAULT 1, |
| | | deleted tinyint NOT NULL DEFAULT 0, |
| | | create_dt datetime2 NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| | | update_dt datetime2 NOT NULL DEFAULT CURRENT_TIMESTAMP |
| | |
| | | GO |
| | | |
| | | EXEC sp_addextendedproperty |
| | | 'MS_Description', N'å
¨å±ä¸ä¸æ', |
| | | 'SCHEMA', N'dbo', |
| | | 'TABLE', N'sj_workflow_task_batch', |
| | | 'COLUMN', N'wf_context' |
| | | GO |
| | | |
| | | EXEC sp_addextendedproperty |
| | | 'MS_Description', N'任塿§è¡æ¶é´', |
| | | 'SCHEMA', N'dbo', |
| | | 'TABLE', N'sj_workflow_task_batch', |
| | |
| | | GO |
| | | |
| | | EXEC sp_addextendedproperty |
| | | 'MS_Description', N'çæ¬å·', |
| | | 'SCHEMA', N'dbo', |
| | | 'TABLE', N'sj_workflow_task_batch', |
| | | 'COLUMN', N'version' |
| | | GO |
| | | |
| | | EXEC sp_addextendedproperty |
| | | 'MS_Description', N'é»è¾å é¤ 1ãå é¤', |
| | | 'SCHEMA', N'dbo', |
| | | 'TABLE', N'sj_workflow_task_batch', |