diff --git a/continew-common/src/main/java/top/continew/admin/common/config/crud/CrudApiPermissionPrefixCache.java b/continew-common/src/main/java/top/continew/admin/common/config/crud/CrudApiPermissionPrefixCache.java index 0735b4ba..80f4205b 100644 --- a/continew-common/src/main/java/top/continew/admin/common/config/crud/CrudApiPermissionPrefixCache.java +++ b/continew-common/src/main/java/top/continew/admin/common/config/crud/CrudApiPermissionPrefixCache.java @@ -61,6 +61,15 @@ public class CrudApiPermissionPrefixCache { PERMISSION_PREFIX_CACHE.clear(); } + /** + * 获取所有缓存 + * + * @return 所有缓存 + */ + public static Map, String> getAll() { + return PERMISSION_PREFIX_CACHE; + } + /** * 解析权限前缀(解析路径获取模块名和资源名) * diff --git a/continew-common/src/main/java/top/continew/admin/common/config/mybatis/DefaultDataPermissionUserDataProvider.java b/continew-common/src/main/java/top/continew/admin/common/config/mybatis/DefaultDataPermissionUserDataProvider.java index c96d9d6f..eafd0ec0 100644 --- a/continew-common/src/main/java/top/continew/admin/common/config/mybatis/DefaultDataPermissionUserDataProvider.java +++ b/continew-common/src/main/java/top/continew/admin/common/config/mybatis/DefaultDataPermissionUserDataProvider.java @@ -34,7 +34,7 @@ public class DefaultDataPermissionUserDataProvider implements DataPermissionUser @Override public boolean isFilter() { - return !UserContextHolder.isAdmin(); + return !UserContextHolder.isSuperAdminUser() && !UserContextHolder.isTenantAdminUser(); } @Override diff --git a/continew-common/src/main/java/top/continew/admin/common/constant/GlobalConstants.java b/continew-common/src/main/java/top/continew/admin/common/constant/GlobalConstants.java new file mode 100644 index 00000000..5235ffef --- /dev/null +++ b/continew-common/src/main/java/top/continew/admin/common/constant/GlobalConstants.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package top.continew.admin.common.constant; + +/** + * 全局常量 + * + * @author Charles7c + * @since 2023/2/9 22:11 + */ +public class GlobalConstants { + + /** + * 根父级 ID + */ + public static final Long ROOT_PARENT_ID = 0L; + + /** + * 布尔值常量 + */ + public static class Boolean { + + /** + * 否 + */ + public static final Integer NO = 0; + + /** + * 是 + */ + public static final Integer YES = 1; + } + + private GlobalConstants() { + } +} diff --git a/continew-common/src/main/java/top/continew/admin/common/constant/SysConstants.java b/continew-common/src/main/java/top/continew/admin/common/constant/SysConstants.java deleted file mode 100644 index b24855c8..00000000 --- a/continew-common/src/main/java/top/continew/admin/common/constant/SysConstants.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package top.continew.admin.common.constant; - -/** - * 系统相关常量 - * - * @author Charles7c - * @since 2023/2/9 22:11 - */ -public class SysConstants { - - /** - * 否 - */ - public static final Integer NO = 0; - - /** - * 是 - */ - public static final Integer YES = 1; - - /** - * 超管用户 ID - */ - public static final Long SUPER_USER_ID = 1L; - - /** - * 顶级部门 ID - */ - public static final Long SUPER_DEPT_ID = 1L; - - /** - * 顶级父 ID - */ - public static final Long SUPER_PARENT_ID = 0L; - - /** - * 超管角色编码 - */ - public static final String SUPER_ROLE_CODE = "admin"; - - /** - * 普通用户角色编码 - */ - public static final String GENERAL_ROLE_CODE = "general"; - - /** - * 超管角色 ID - */ - public static final Long SUPER_ROLE_ID = 1L; - - /** - * 普通用户角色 ID - */ - public static final Long GENERAL_ROLE_ID = 2L; - - /** - * 全部权限标识 - */ - public static final String ALL_PERMISSION = "*:*:*"; - - /** - * 登录 URI - */ - public static final String LOGIN_URI = "/auth/login"; - - /** - * 登出 URI - */ - public static final String LOGOUT_URI = "/auth/logout"; - - /** - * 租户管理员角色编码 - */ - public static final String TENANT_ADMIN_ROLE_CODE = "tenant_admin"; - - private SysConstants() { - } -} diff --git a/continew-common/src/main/java/top/continew/admin/common/context/UserContext.java b/continew-common/src/main/java/top/continew/admin/common/context/UserContext.java index e4bfa342..2f71e326 100644 --- a/continew-common/src/main/java/top/continew/admin/common/context/UserContext.java +++ b/continew-common/src/main/java/top/continew/admin/common/context/UserContext.java @@ -17,9 +17,12 @@ package top.continew.admin.common.context; import cn.hutool.core.collection.CollUtil; +import cn.hutool.extra.spring.SpringUtil; import lombok.Data; import lombok.NoArgsConstructor; -import top.continew.admin.common.constant.SysConstants; +import top.continew.admin.common.config.TenantExtensionProperties; +import top.continew.admin.common.constant.GlobalConstants; +import top.continew.admin.common.enums.RoleCodeEnum; import top.continew.starter.core.util.CollUtils; import java.io.Serial; @@ -101,23 +104,16 @@ public class UserContext implements Serializable { this.passwordExpirationDays = passwordExpirationDays; } + /** + * 设置角色 + * + * @param roles 角色 + */ public void setRoles(Set roles) { this.roles = roles; this.roleCodes = CollUtils.mapToSet(roles, RoleContext::getCode); } - /** - * 是否为管理员 - * - * @return true:是;false:否 - */ - public boolean isAdmin() { - if (CollUtil.isEmpty(roleCodes)) { - return false; - } - return roleCodes.contains(SysConstants.SUPER_ROLE_CODE); - } - /** * 密码是否已过期 * @@ -125,7 +121,7 @@ public class UserContext implements Serializable { */ public boolean isPasswordExpired() { // 永久有效 - if (this.passwordExpirationDays == null || this.passwordExpirationDays <= SysConstants.NO) { + if (this.passwordExpirationDays == null || this.passwordExpirationDays <= GlobalConstants.Boolean.NO) { return false; } // 初始密码(第三方登录用户)暂不提示修改 @@ -134,4 +130,29 @@ public class UserContext implements Serializable { } return this.pwdResetTime.plusDays(this.passwordExpirationDays).isBefore(LocalDateTime.now()); } + + /** + * 是否为超级管理员用户 + * + * @return true:是;false:否 + */ + public boolean isSuperAdminUser() { + if (CollUtil.isEmpty(roleCodes)) { + return false; + } + return roleCodes.contains(RoleCodeEnum.SUPER_ADMIN.getCode()); + } + + /** + * 是否为租户管理员用户 + * + * @return true:是;false:否 + */ + public boolean isTenantAdminUser() { + if (CollUtil.isEmpty(roleCodes)) { + return false; + } + TenantExtensionProperties tenantExtensionProperties = SpringUtil.getBean(TenantExtensionProperties.class); + return !tenantExtensionProperties.isDefaultTenant() && roleCodes.contains(RoleCodeEnum.TENANT_ADMIN.getCode()); + } } diff --git a/continew-common/src/main/java/top/continew/admin/common/context/UserContextHolder.java b/continew-common/src/main/java/top/continew/admin/common/context/UserContextHolder.java index 48facc3f..92ec08d1 100644 --- a/continew-common/src/main/java/top/continew/admin/common/context/UserContextHolder.java +++ b/continew-common/src/main/java/top/continew/admin/common/context/UserContextHolder.java @@ -181,12 +181,22 @@ public class UserContextHolder { } /** - * 是否为管理员 + * 是否为超级管理员用户 * - * @return 是否为管理员 + * @return true:是;false:否 */ - public static boolean isAdmin() { + public static boolean isSuperAdminUser() { StpUtil.checkLogin(); - return getContext().isAdmin(); + return getContext().isSuperAdminUser(); + } + + /** + * 是否为租户管理员用户 + * + * @return true:是;false:否 + */ + public static boolean isTenantAdminUser() { + StpUtil.checkLogin(); + return getContext().isTenantAdminUser(); } } diff --git a/continew-common/src/main/java/top/continew/admin/common/enums/RoleCodeEnum.java b/continew-common/src/main/java/top/continew/admin/common/enums/RoleCodeEnum.java new file mode 100644 index 00000000..1945cbe0 --- /dev/null +++ b/continew-common/src/main/java/top/continew/admin/common/enums/RoleCodeEnum.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package top.continew.admin.common.enums; + +import cn.hutool.extra.spring.SpringUtil; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import top.continew.admin.common.config.TenantExtensionProperties; +import top.continew.starter.extension.tenant.context.TenantContextHolder; + +import java.util.List; + +/** + * 角色编码枚举 + * + * @author Charles7c + * @since 2025/7/26 19:18 + */ +@Getter +@RequiredArgsConstructor +public enum RoleCodeEnum { + + /** + * 超级管理员(内置且仅有一位超级管理员) + */ + SUPER_ADMIN("super_admin", "超级管理员"), + + /** + * 租户管理员 + */ + TENANT_ADMIN("admin", "系统管理员"), + + /** + * 系统管理员 + */ + SYSTEM_ADMIN("sys_admin", "系统管理员"), + + /** + * 普通用户 + */ + GENERAL_USER("general", "普通用户"); + + private final String code; + private final String description; + + /** + * 获取超级管理员角色编码列表 + * + * @return 超级管理员角色编码列表 + */ + public static List getSuperRoleCodes() { + if (TenantContextHolder.isTenantDisabled() || SpringUtil.getBean(TenantExtensionProperties.class) + .isDefaultTenant()) { + return List.of(SUPER_ADMIN.getCode()); + } + return List.of(SUPER_ADMIN.getCode(), TENANT_ADMIN.getCode()); + } + + /** + * 判断是否为超级管理员角色编码 + * + * @param code 角色编码 + * @return 是否为超级管理员角色编码 + */ + public static boolean isSuperRoleCode(String code) { + return getSuperRoleCodes().contains(code); + } +} diff --git a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/service/impl/TenantServiceImpl.java b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/service/impl/TenantServiceImpl.java index af761df1..246177e5 100644 --- a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/service/impl/TenantServiceImpl.java +++ b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/service/impl/TenantServiceImpl.java @@ -30,8 +30,8 @@ import top.continew.admin.common.api.tenant.TenantDataApi; import top.continew.admin.common.base.service.BaseServiceImpl; import top.continew.admin.common.config.TenantExtensionProperties; import top.continew.admin.common.constant.CacheConstants; -import top.continew.admin.common.constant.SysConstants; import top.continew.admin.common.enums.DisEnableStatusEnum; +import top.continew.admin.common.enums.RoleCodeEnum; import top.continew.admin.common.model.dto.TenantDTO; import top.continew.admin.tenant.constant.TenantCacheConstants; import top.continew.admin.tenant.constant.TenantConstants; @@ -170,7 +170,7 @@ public class TenantServiceImpl extends BaseServiceImpl TenantUtils.execute(tenantId, () -> { - Long roleId = roleApi.getIdByCode(SysConstants.TENANT_ADMIN_ROLE_CODE); + Long roleId = roleApi.getIdByCode(RoleCodeEnum.TENANT_ADMIN.getCode()); List oldMenuIdList = roleMenuApi.listMenuIdByRoleIds(List.of(roleId)); Collection addMenuIdList = CollUtil.disjunction(newMenuIds, oldMenuIdList); if (CollUtil.isNotEmpty(addMenuIdList)) { diff --git a/continew-server/src/main/java/top/continew/admin/config/log/LogDaoLocalImpl.java b/continew-server/src/main/java/top/continew/admin/config/log/LogDaoLocalImpl.java index ed2112e7..79fa85cd 100644 --- a/continew-server/src/main/java/top/continew/admin/config/log/LogDaoLocalImpl.java +++ b/continew-server/src/main/java/top/continew/admin/config/log/LogDaoLocalImpl.java @@ -29,12 +29,12 @@ import cn.hutool.json.JSONUtil; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpHeaders; import org.springframework.scheduling.annotation.Async; +import top.continew.admin.auth.constant.AuthConstants; import top.continew.admin.auth.enums.AuthTypeEnum; import top.continew.admin.auth.model.req.AccountLoginReq; import top.continew.admin.auth.model.req.EmailLoginReq; import top.continew.admin.auth.model.req.LoginReq; import top.continew.admin.auth.model.req.PhoneLoginReq; -import top.continew.admin.common.constant.SysConstants; import top.continew.admin.system.enums.LogStatusEnum; import top.continew.admin.system.mapper.LogMapper; import top.continew.admin.system.model.entity.LogDO; @@ -92,7 +92,8 @@ public class LogDaoLocalImpl implements LogDao { // 保存记录 if (TenantContextHolder.isTenantEnabled()) { // 异步无法获取租户 ID - String tenantId = logRequest.getHeaders().get(SpringUtil.getBean(TenantProperties.class).getTenantIdHeader()); + String tenantId = logRequest.getHeaders() + .get(SpringUtil.getBean(TenantProperties.class).getTenantIdHeader()); if (StrUtil.isNotBlank(tenantId)) { TenantUtils.execute(Long.parseLong(tenantId), () -> logMapper.insert(logDO)); return; @@ -154,13 +155,13 @@ public class LogDaoLocalImpl implements LogDao { String requestUri = URLUtil.getPath(logDO.getRequestUrl()); // 解析退出接口信息 String responseBody = logResponse.getBody(); - if (requestUri.startsWith(SysConstants.LOGOUT_URI) && StrUtil.isNotBlank(responseBody)) { + if (requestUri.startsWith(AuthConstants.LOGOUT_URI) && StrUtil.isNotBlank(responseBody)) { R result = JSONUtil.toBean(responseBody, R.class); logDO.setCreateUser(Convert.toLong(result.getData(), null)); return; } // 解析登录接口信息 - if (requestUri.startsWith(SysConstants.LOGIN_URI) && LogStatusEnum.SUCCESS.equals(logDO.getStatus())) { + if (requestUri.startsWith(AuthConstants.LOGIN_URI) && LogStatusEnum.SUCCESS.equals(logDO.getStatus())) { String requestBody = logRequest.getBody(); logDO.setDescription(JSONUtil.toBean(requestBody, LoginReq.class).getAuthType().getDescription() + "登录"); // 解析账号登录用户为操作人 diff --git a/continew-server/src/main/java/top/continew/admin/config/satoken/SaTokenConfiguration.java b/continew-server/src/main/java/top/continew/admin/config/satoken/SaTokenConfiguration.java index 5ac97c72..74e13780 100644 --- a/continew-server/src/main/java/top/continew/admin/config/satoken/SaTokenConfiguration.java +++ b/continew-server/src/main/java/top/continew/admin/config/satoken/SaTokenConfiguration.java @@ -27,6 +27,7 @@ import cn.dev33.satoken.sign.template.SaSignUtil; import cn.dev33.satoken.stp.StpInterface; import cn.dev33.satoken.stp.StpUtil; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.aop.framework.AopProxyUtils; import org.springframework.aop.support.AopUtils; import org.springframework.boot.context.event.ApplicationReadyEvent; @@ -54,6 +55,7 @@ import java.util.*; * @author chengzi * @since 2022/12/19 22:13 */ +@Slf4j @Configuration @RequiredArgsConstructor public class SaTokenConfiguration { @@ -133,5 +135,6 @@ public class SaTokenConfiguration { // 转回数组 properties.getSecurity().setExcludes(allExcludes.toArray(new String[0])); } + log.debug("缓存 CRUD API 权限前缀完成:{}", CrudApiPermissionPrefixCache.getAll().values()); } } diff --git a/continew-server/src/main/java/top/continew/admin/controller/CaptchaController.java b/continew-server/src/main/java/top/continew/admin/controller/CaptchaController.java index 398f1015..130f40ab 100644 --- a/continew-server/src/main/java/top/continew/admin/controller/CaptchaController.java +++ b/continew-server/src/main/java/top/continew/admin/controller/CaptchaController.java @@ -46,7 +46,7 @@ import org.springframework.web.bind.annotation.*; import top.continew.admin.auth.model.resp.CaptchaResp; import top.continew.admin.common.config.CaptchaProperties; import top.continew.admin.common.constant.CacheConstants; -import top.continew.admin.common.constant.SysConstants; +import top.continew.admin.common.constant.GlobalConstants; import top.continew.admin.system.enums.OptionCategoryEnum; import top.continew.admin.system.model.entity.SmsConfigDO; import top.continew.admin.system.service.OptionService; @@ -119,7 +119,7 @@ public class CaptchaController { @GetMapping("/image") public CaptchaResp getImageCaptcha() { int loginCaptchaEnabled = optionService.getValueByCode2Int("LOGIN_CAPTCHA_ENABLED"); - if (SysConstants.NO.equals(loginCaptchaEnabled)) { + if (GlobalConstants.Boolean.NO.equals(loginCaptchaEnabled)) { return CaptchaResp.builder().isEnabled(false).build(); } String uuid = IdUtil.fastUUID(); diff --git a/continew-server/src/main/java/top/continew/admin/job/DemoEnvironmentJob.java b/continew-server/src/main/java/top/continew/admin/job/DemoEnvironmentJob.java index 882f7c93..9ec81b6a 100644 --- a/continew-server/src/main/java/top/continew/admin/job/DemoEnvironmentJob.java +++ b/continew-server/src/main/java/top/continew/admin/job/DemoEnvironmentJob.java @@ -77,10 +77,8 @@ public class DemoEnvironmentJob { private static final Long DELETE_FLAG = 10000L; private static final Long MESSAGE_FLAG = 0L; private static final List USER_FLAG = List - .of(1L, 547889293968801822L, 547889293968801823L, 547889293968801824L, 547889293968801825L, - 547889293968801826L, 547889293968801827L, 547889293968801828L, 547889293968801829L, - 547889293968801830L, 547889293968801831L, 547889293968801832L, 547889293968801833L, 547889293968801834L); - private static final List ROLE_FLAG = List.of(1L, 2L, 547888897925840927L, 547888897925840928L); + .of(1L, 547889293968801822L, 547889293968801823L, 547889293968801824L, 547889293968801825L, 547889293968801826L, 547889293968801827L, 547889293968801828L, 547889293968801829L, 547889293968801830L, 547889293968801831L, 547889293968801832L, 547889293968801833L, 547889293968801834L); + private static final List ROLE_FLAG = List.of(1L, 2L, 3L, 547888897925840927L, 547888897925840928L); private static final Long DEPT_FLAG = 547887852587843611L; /** diff --git a/continew-server/src/main/resources/config/application.yml b/continew-server/src/main/resources/config/application.yml index 760566bd..a5f9ce5f 100644 --- a/continew-server/src/main/resources/config/application.yml +++ b/continew-server/src/main/resources/config/application.yml @@ -206,7 +206,7 @@ continew-starter.tenant: tenant-id-header: X-Tenant-Id # 请求头中租户编码键名 tenant-code-header: X-Tenant-Code - # 默认租户 ID:超管用户所在租户(默认:0) + # 默认租户 ID:超级管理员用户所在租户(默认:0) default-tenant-id: 0 # 忽略表(忽略拼接租户条件) ignore-tables: diff --git a/continew-server/src/main/resources/db/changelog/mysql/main_data.sql b/continew-server/src/main/resources/db/changelog/mysql/main_data.sql index 361c30a1..70ad9d5c 100644 --- a/continew-server/src/main/resources/db/changelog/mysql/main_data.sql +++ b/continew-server/src/main/resources/db/changelog/mysql/main_data.sql @@ -164,8 +164,9 @@ VALUES INSERT INTO `sys_role` (`id`, `name`, `code`, `data_scope`, `description`, `sort`, `is_system`, `create_user`, `create_time`) VALUES -(1, '系统管理员', 'admin', 1, '系统初始角色', 1, b'1', 1, NOW()), -(2, '普通用户', 'general', 4, '系统初始角色', 2, b'1', 1, NOW()), +(1, '超级管理员', 'super_admin', 1, '系统初始角色', 0, b'1', 1, NOW()), +(2, '系统管理员', 'sys_admin', 1, NULL, 1, b'0', 1, NOW()), +(3, '普通用户', 'general', 4, NULL, 2, b'0', 1, NOW()), (547888897925840927, '测试人员', 'tester', 5, NULL, 3, b'0', 1, NOW()), (547888897925840928, '研发人员', 'developer', 4, NULL, 4, b'0', 1, NOW()); @@ -173,7 +174,7 @@ VALUES INSERT INTO `sys_user` (`id`, `username`, `nickname`, `password`, `gender`, `email`, `phone`, `avatar`, `description`, `status`, `is_system`, `pwd_reset_time`, `dept_id`, `create_user`, `create_time`) VALUES -(1, 'admin', '系统管理员', '{bcrypt}$2a$10$4jGwK2BMJ7FgVR.mgwGodey8.xR8FLoU1XSXpxJ9nZQt.pufhasSa', 1, '42190c6c5639d2ca4edb4150a35e058559ccf8270361a23745a2fd285a273c28', '5bda89a4609a65546422ea56bfe5eab4', NULL, '系统初始用户', 1, b'1', NOW(), 1, 1, NOW()), +(1, 'admin', '超级管理员', '{bcrypt}$2a$10$4jGwK2BMJ7FgVR.mgwGodey8.xR8FLoU1XSXpxJ9nZQt.pufhasSa', 1, '42190c6c5639d2ca4edb4150a35e058559ccf8270361a23745a2fd285a273c28', '5bda89a4609a65546422ea56bfe5eab4', NULL, '系统初始用户', 1, b'1', NOW(), 1, 1, NOW()), (547889293968801822, 'test', '测试员', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 2, NULL, NULL, NULL, NULL, 1, b'0', NOW(), 547887852587843593, 1, NOW()), (547889293968801823, 'Charles', 'Charles', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '代码写到极致,就是艺术。', 1, b'0', NOW(), 547887852587843595, 1, NOW()), (547889293968801824, 'Yoofff', 'Yoofff', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '弱小和无知不是生存的障碍,傲慢才是。', 2, b'0', NOW(), 1, 1, NOW()), diff --git a/continew-server/src/main/resources/db/changelog/postgresql/main_data.sql b/continew-server/src/main/resources/db/changelog/postgresql/main_data.sql index 7ca67333..d83635f3 100644 --- a/continew-server/src/main/resources/db/changelog/postgresql/main_data.sql +++ b/continew-server/src/main/resources/db/changelog/postgresql/main_data.sql @@ -164,8 +164,9 @@ VALUES INSERT INTO "sys_role" ("id", "name", "code", "data_scope", "description", "sort", "is_system", "create_user", "create_time") VALUES -(1, '系统管理员', 'admin', 1, '系统初始角色', 1, true, 1, NOW()), -(2, '普通用户', 'general', 4, '系统初始角色', 2, true, 1, NOW()), +(1, '超级管理员', 'super_admin', 1, '系统初始角色', 0, true, 1, NOW()), +(2, '系统管理员', 'sys_admin', 1, NULL, 1, false, 1, NOW()), +(3, '普通用户', 'general', 4, NULL, 2, false, 1, NOW()), (547888897925840927, '测试人员', 'tester', 5, NULL, 3, false, 1, NOW()), (547888897925840928, '研发人员', 'developer', 4, NULL, 4, false, 1, NOW()); @@ -173,7 +174,7 @@ VALUES INSERT INTO "sys_user" ("id", "username", "nickname", "password", "gender", "email", "phone", "avatar", "description", "status", "is_system", "pwd_reset_time", "dept_id", "create_user", "create_time") VALUES -(1, 'admin', '系统管理员', '{bcrypt}$2a$10$4jGwK2BMJ7FgVR.mgwGodey8.xR8FLoU1XSXpxJ9nZQt.pufhasSa', 1, '42190c6c5639d2ca4edb4150a35e058559ccf8270361a23745a2fd285a273c28', '5bda89a4609a65546422ea56bfe5eab4', NULL, '系统初始用户', 1, true, NOW(), 1, 1, NOW()), +(1, 'admin', '超级管理员', '{bcrypt}$2a$10$4jGwK2BMJ7FgVR.mgwGodey8.xR8FLoU1XSXpxJ9nZQt.pufhasSa', 1, '42190c6c5639d2ca4edb4150a35e058559ccf8270361a23745a2fd285a273c28', '5bda89a4609a65546422ea56bfe5eab4', NULL, '系统初始用户', 1, true, NOW(), 1, 1, NOW()), (547889293968801822, 'test', '测试员', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 2, NULL, NULL, NULL, NULL, 1, false, NOW(), 547887852587843593, 1, NOW()), (547889293968801823, 'Charles', 'Charles', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '代码写到极致,就是艺术。', 1, false, NOW(), 547887852587843595, 1, NOW()), (547889293968801824, 'Yoofff', 'Yoofff', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '弱小和无知不是生存的障碍,傲慢才是。', 1, false, NOW(), 1, 1, NOW()), diff --git a/continew-system/src/main/java/top/continew/admin/auth/constant/AuthConstants.java b/continew-system/src/main/java/top/continew/admin/auth/constant/AuthConstants.java new file mode 100644 index 00000000..37c4de73 --- /dev/null +++ b/continew-system/src/main/java/top/continew/admin/auth/constant/AuthConstants.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package top.continew.admin.auth.constant; + +/** + * 认证相关常量 + * + * @author Charles7c + * @since 2025/7/26 12:05 + */ +public class AuthConstants { + + /** + * 登录 URI + */ + public static final String LOGIN_URI = "/auth/login"; + + /** + * 登出 URI + */ + public static final String LOGOUT_URI = "/auth/logout"; + + private AuthConstants() { + } +} diff --git a/continew-system/src/main/java/top/continew/admin/auth/handler/AccountLoginHandler.java b/continew-system/src/main/java/top/continew/admin/auth/handler/AccountLoginHandler.java index ed186727..26c6cbe5 100644 --- a/continew-system/src/main/java/top/continew/admin/auth/handler/AccountLoginHandler.java +++ b/continew-system/src/main/java/top/continew/admin/auth/handler/AccountLoginHandler.java @@ -30,7 +30,7 @@ import top.continew.admin.auth.enums.AuthTypeEnum; import top.continew.admin.auth.model.req.AccountLoginReq; import top.continew.admin.auth.model.resp.LoginResp; import top.continew.admin.common.constant.CacheConstants; -import top.continew.admin.common.constant.SysConstants; +import top.continew.admin.common.constant.GlobalConstants; import top.continew.admin.common.util.SecureUtils; import top.continew.admin.system.enums.PasswordPolicyEnum; import top.continew.admin.system.model.entity.user.UserDO; @@ -78,7 +78,7 @@ public class AccountLoginHandler extends AbstractLoginHandler { super.preLogin(req, client, request); // 校验验证码 int loginCaptchaEnabled = optionService.getValueByCode2Int("LOGIN_CAPTCHA_ENABLED"); - if (SysConstants.YES.equals(loginCaptchaEnabled)) { + if (GlobalConstants.Boolean.YES.equals(loginCaptchaEnabled)) { ValidationUtils.throwIfBlank(req.getCaptcha(), "验证码不能为空"); ValidationUtils.throwIfBlank(req.getUuid(), "验证码标识不能为空"); String captchaKey = CacheConstants.CAPTCHA_KEY_PREFIX + req.getUuid(); @@ -104,7 +104,7 @@ public class AccountLoginHandler extends AbstractLoginHandler { private void checkUserLocked(String username, HttpServletRequest request, boolean isError) { // 不锁定 int maxErrorCount = optionService.getValueByCode2Int(PasswordPolicyEnum.PASSWORD_ERROR_LOCK_COUNT.name()); - if (maxErrorCount <= SysConstants.NO) { + if (maxErrorCount <= GlobalConstants.Boolean.NO) { return; } // 检测是否已被锁定 diff --git a/continew-system/src/main/java/top/continew/admin/auth/handler/SocialLoginHandler.java b/continew-system/src/main/java/top/continew/admin/auth/handler/SocialLoginHandler.java index bc4cc668..606f9664 100644 --- a/continew-system/src/main/java/top/continew/admin/auth/handler/SocialLoginHandler.java +++ b/continew-system/src/main/java/top/continew/admin/auth/handler/SocialLoginHandler.java @@ -38,9 +38,10 @@ import top.continew.admin.auth.enums.AuthTypeEnum; import top.continew.admin.auth.model.req.SocialLoginReq; import top.continew.admin.auth.model.resp.LoginResp; import top.continew.admin.common.constant.RegexConstants; -import top.continew.admin.common.constant.SysConstants; import top.continew.admin.common.enums.DisEnableStatusEnum; import top.continew.admin.common.enums.GenderEnum; +import top.continew.admin.common.enums.RoleCodeEnum; +import top.continew.admin.system.constant.SystemConstants; import top.continew.admin.system.enums.MessageTemplateEnum; import top.continew.admin.system.enums.MessageTypeEnum; import top.continew.admin.system.model.entity.user.UserDO; @@ -107,11 +108,12 @@ public class SocialLoginHandler extends AbstractLoginHandler { user.setGender(GenderEnum.valueOf(authUser.getGender().name())); } user.setAvatar(authUser.getAvatar()); - user.setDeptId(SysConstants.SUPER_DEPT_ID); + user.setDeptId(SystemConstants.SUPER_DEPT_ID); user.setStatus(DisEnableStatusEnum.ENABLE); userService.save(user); Long userId = user.getId(); - userRoleService.assignRolesToUser(Collections.singletonList(SysConstants.GENERAL_ROLE_ID), userId); + userRoleService.assignRolesToUser(Collections.singletonList(roleService + .getIdByCode(RoleCodeEnum.GENERAL_USER.getCode())), userId); userSocial = new UserSocialDO(); userSocial.setUserId(userId); userSocial.setSource(source); diff --git a/continew-system/src/main/java/top/continew/admin/auth/service/impl/AuthServiceImpl.java b/continew-system/src/main/java/top/continew/admin/auth/service/impl/AuthServiceImpl.java index 87bd8f9d..ef94f6da 100644 --- a/continew-system/src/main/java/top/continew/admin/auth/service/impl/AuthServiceImpl.java +++ b/continew-system/src/main/java/top/continew/admin/auth/service/impl/AuthServiceImpl.java @@ -31,9 +31,9 @@ import top.continew.admin.auth.model.req.LoginReq; import top.continew.admin.auth.model.resp.LoginResp; import top.continew.admin.auth.model.resp.RouteResp; import top.continew.admin.auth.service.AuthService; -import top.continew.admin.common.constant.SysConstants; import top.continew.admin.common.context.RoleContext; import top.continew.admin.common.enums.DisEnableStatusEnum; +import top.continew.admin.system.constant.SystemConstants; import top.continew.admin.system.enums.MenuTypeEnum; import top.continew.admin.system.model.resp.ClientResp; import top.continew.admin.system.model.resp.MenuResp; @@ -93,8 +93,8 @@ public class AuthServiceImpl implements AuthService { } // 查询菜单列表 Set menuSet = new LinkedHashSet<>(); - if (roleSet.stream().anyMatch(r -> SysConstants.SUPER_ROLE_ID.equals(r.getId()))) { - menuSet.addAll(menuService.listByRoleId(SysConstants.SUPER_ROLE_ID)); + if (roleSet.stream().anyMatch(r -> SystemConstants.SUPER_ADMIN_ROLE_ID.equals(r.getId()))) { + menuSet.addAll(menuService.listByRoleId(SystemConstants.SUPER_ADMIN_ROLE_ID)); } else { roleSet.forEach(r -> menuSet.addAll(menuService.listByRoleId(r.getId()))); } diff --git a/continew-system/src/main/java/top/continew/admin/system/api/RoleApiImpl.java b/continew-system/src/main/java/top/continew/admin/system/api/RoleApiImpl.java index 40e0146e..e5639725 100644 --- a/continew-system/src/main/java/top/continew/admin/system/api/RoleApiImpl.java +++ b/continew-system/src/main/java/top/continew/admin/system/api/RoleApiImpl.java @@ -19,11 +19,8 @@ package top.continew.admin.system.api; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import top.continew.admin.common.api.system.RoleApi; -import top.continew.admin.system.model.entity.RoleDO; import top.continew.admin.system.service.RoleService; -import java.util.Optional; - /** * 角色业务 API 实现 * @@ -38,7 +35,7 @@ public class RoleApiImpl implements RoleApi { @Override public Long getIdByCode(String code) { - return Optional.ofNullable(baseService.getByCode(code)).map(RoleDO::getId).orElse(null); + return baseService.getIdByCode(code); } @Override diff --git a/continew-system/src/main/java/top/continew/admin/system/api/TenantDataApiForSystemImpl.java b/continew-system/src/main/java/top/continew/admin/system/api/TenantDataApiForSystemImpl.java index 017b0f93..5d02da58 100644 --- a/continew-system/src/main/java/top/continew/admin/system/api/TenantDataApiForSystemImpl.java +++ b/continew-system/src/main/java/top/continew/admin/system/api/TenantDataApiForSystemImpl.java @@ -27,11 +27,12 @@ import org.springframework.transaction.annotation.Transactional; import top.continew.admin.common.api.tenant.PackageMenuApi; import top.continew.admin.common.api.tenant.TenantApi; import top.continew.admin.common.api.tenant.TenantDataApi; +import top.continew.admin.common.constant.GlobalConstants; import top.continew.admin.common.constant.RegexConstants; -import top.continew.admin.common.constant.SysConstants; import top.continew.admin.common.enums.DataScopeEnum; import top.continew.admin.common.enums.DisEnableStatusEnum; import top.continew.admin.common.enums.GenderEnum; +import top.continew.admin.common.enums.RoleCodeEnum; import top.continew.admin.common.model.dto.TenantDTO; import top.continew.admin.common.util.SecureUtils; import top.continew.admin.system.mapper.*; @@ -44,7 +45,7 @@ import top.continew.admin.system.model.entity.RoleDO; import top.continew.admin.system.model.entity.user.UserDO; import top.continew.admin.system.service.FileService; import top.continew.admin.system.service.RoleMenuService; -import top.continew.admin.system.service.RoleService; +import top.continew.admin.system.service.UserRoleService; import top.continew.starter.core.util.CollUtils; import top.continew.starter.core.util.ExceptionUtils; import top.continew.starter.core.util.validation.ValidationUtils; @@ -66,7 +67,7 @@ public class TenantDataApiForSystemImpl implements TenantDataApi { private final PackageMenuApi packageMenuApi; private final TenantApi tenantApi; - private final RoleService roleService; + private final UserRoleService userRoleService; private final FileService fileService; private final RoleMenuService roleMenuService; private final DeptMapper deptMapper; @@ -97,7 +98,7 @@ public class TenantDataApiForSystemImpl implements TenantDataApi { // 初始化管理用户 Long userId = this.initUserData(tenant, deptId); // 用户绑定角色 - roleService.assignToUsers(roleId, ListUtil.of(userId)); + userRoleService.assignRoleToUsers(roleId, ListUtil.of(userId)); // 租户绑定用户 tenantApi.bindAdminUser(tenantId, userId); }); @@ -146,11 +147,12 @@ public class TenantDataApiForSystemImpl implements TenantDataApi { private Long initDeptData(TenantDTO tenant) { DeptDO dept = new DeptDO(); dept.setName(tenant.getName()); - dept.setParentId(SysConstants.SUPER_PARENT_ID); - dept.setAncestors("0"); + dept.setParentId(GlobalConstants.ROOT_PARENT_ID); + dept.setAncestors(GlobalConstants.ROOT_PARENT_ID.toString()); dept.setDescription("系统初始部门"); dept.setSort(1); dept.setStatus(DisEnableStatusEnum.ENABLE); + dept.setIsSystem(true); deptMapper.insert(dept); return dept.getId(); } @@ -163,8 +165,9 @@ public class TenantDataApiForSystemImpl implements TenantDataApi { */ private Long initRoleData(TenantDTO tenant) { RoleDO role = new RoleDO(); - role.setName("系统管理员"); - role.setCode(SysConstants.TENANT_ADMIN_ROLE_CODE); + RoleCodeEnum tenantAdmin = RoleCodeEnum.TENANT_ADMIN; + role.setName(tenantAdmin.getDescription()); + role.setCode(tenantAdmin.getCode()); role.setDataScope(DataScopeEnum.ALL); role.setDescription("系统初始角色"); role.setSort(1); @@ -191,7 +194,7 @@ public class TenantDataApiForSystemImpl implements TenantDataApi { // 初始化用户 UserDO user = new UserDO(); user.setUsername(tenant.getUsername()); - user.setNickname("系统管理员"); + user.setNickname(RoleCodeEnum.TENANT_ADMIN.getDescription()); user.setPassword(rawPassword); user.setGender(GenderEnum.UNKNOWN); user.setDescription("系统初始用户"); diff --git a/continew-system/src/main/java/top/continew/admin/system/config/mail/MailConfigurerImpl.java b/continew-system/src/main/java/top/continew/admin/system/config/mail/MailConfigurerImpl.java index e7deec96..ef9849bb 100644 --- a/continew-system/src/main/java/top/continew/admin/system/config/mail/MailConfigurerImpl.java +++ b/continew-system/src/main/java/top/continew/admin/system/config/mail/MailConfigurerImpl.java @@ -20,7 +20,7 @@ import cn.hutool.core.map.MapUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -import top.continew.admin.common.constant.SysConstants; +import top.continew.admin.common.constant.GlobalConstants; import top.continew.admin.system.enums.OptionCategoryEnum; import top.continew.admin.system.service.OptionService; import top.continew.starter.messaging.mail.core.MailConfig; @@ -52,7 +52,7 @@ public class MailConfigurerImpl implements MailConfigurer { mailConfig.setPort(MapUtil.getInt(map, "MAIL_PORT")); mailConfig.setUsername(MapUtil.getStr(map, "MAIL_USERNAME")); mailConfig.setPassword(MapUtil.getStr(map, "MAIL_PASSWORD")); - mailConfig.setSslEnabled(SysConstants.YES.equals(MapUtil.getInt(map, "MAIL_SSL_ENABLED"))); + mailConfig.setSslEnabled(GlobalConstants.Boolean.YES.equals(MapUtil.getInt(map, "MAIL_SSL_ENABLED"))); if (mailConfig.isSslEnabled()) { mailConfig.setSslPort(MapUtil.getInt(map, "MAIL_SSL_PORT")); } diff --git a/continew-system/src/main/java/top/continew/admin/system/constant/SystemConstants.java b/continew-system/src/main/java/top/continew/admin/system/constant/SystemConstants.java new file mode 100644 index 00000000..c45c77c2 --- /dev/null +++ b/continew-system/src/main/java/top/continew/admin/system/constant/SystemConstants.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package top.continew.admin.system.constant; + +/** + * 系统管理相关常量 + * + * @author Charles7c + * @since 2025/7/26 12:05 + */ +public class SystemConstants { + + /** + * 超级管理员角色 ID(内置且仅有一位超级管理员用户) + */ + public static final Long SUPER_ADMIN_ROLE_ID = 1L; + + /** + * 顶级部门 ID + */ + public static final Long SUPER_DEPT_ID = 1L; + + /** + * 全部权限标识 + */ + public static final String ALL_PERMISSION = "*:*:*"; + + private SystemConstants() { + } +} diff --git a/continew-system/src/main/java/top/continew/admin/system/enums/PasswordPolicyEnum.java b/continew-system/src/main/java/top/continew/admin/system/enums/PasswordPolicyEnum.java index 069e509c..2db94e98 100644 --- a/continew-system/src/main/java/top/continew/admin/system/enums/PasswordPolicyEnum.java +++ b/continew-system/src/main/java/top/continew/admin/system/enums/PasswordPolicyEnum.java @@ -25,7 +25,7 @@ import cn.hutool.extra.spring.SpringUtil; import lombok.Getter; import lombok.RequiredArgsConstructor; import top.continew.admin.common.constant.RegexConstants; -import top.continew.admin.common.constant.SysConstants; +import top.continew.admin.common.constant.GlobalConstants; import top.continew.admin.system.model.entity.user.UserDO; import top.continew.admin.system.service.OptionService; import top.continew.admin.system.service.UserPasswordHistoryService; @@ -47,7 +47,7 @@ public enum PasswordPolicyEnum { /** * 密码错误锁定阈值 */ - PASSWORD_ERROR_LOCK_COUNT("密码错误锁定阈值取值范围为 %d-%d", SysConstants.NO, 10, "由于您连续 %s 次输入错误密码,账号已被锁定 %s 分钟,预计解锁时间为 %s,请稍后再试"), + PASSWORD_ERROR_LOCK_COUNT("密码错误锁定阈值取值范围为 %d-%d", GlobalConstants.Boolean.NO, 10, "由于您连续 %s 次输入错误密码,账号已被锁定 %s 分钟,预计解锁时间为 %s,请稍后再试"), /** * 账号锁定时长(分钟) @@ -57,12 +57,12 @@ public enum PasswordPolicyEnum { /** * 密码有效期(天) */ - PASSWORD_EXPIRATION_DAYS("密码有效期取值范围为 %d-%d 天", SysConstants.NO, 999, null), + PASSWORD_EXPIRATION_DAYS("密码有效期取值范围为 %d-%d 天", GlobalConstants.Boolean.NO, 999, null), /** * 密码到期提醒(天) */ - PASSWORD_EXPIRATION_WARNING_DAYS("密码到期提醒取值范围为 %d-%d 天", SysConstants.NO, 998, null) { + PASSWORD_EXPIRATION_WARNING_DAYS("密码到期提醒取值范围为 %d-%d 天", GlobalConstants.Boolean.NO, 998, null) { @Override public void validateRange(int value, Map policyMap) { if (CollUtil.isEmpty(policyMap)) { @@ -72,7 +72,7 @@ public enum PasswordPolicyEnum { Integer passwordExpirationDays = ObjectUtil.defaultIfNull(Convert.toInt(policyMap .get(PASSWORD_EXPIRATION_DAYS.name())), SpringUtil.getBean(OptionService.class) .getValueByCode2Int(PASSWORD_EXPIRATION_DAYS.name())); - if (passwordExpirationDays > SysConstants.NO) { + if (passwordExpirationDays > GlobalConstants.Boolean.NO) { ValidationUtils.throwIf(value >= passwordExpirationDays, "密码到期提醒时间应小于密码有效期"); return; } @@ -98,16 +98,17 @@ public enum PasswordPolicyEnum { /** * 密码是否必须包含特殊字符 */ - PASSWORD_REQUIRE_SYMBOLS("密码是否必须包含特殊字符取值只能为是(%d)或否(%d)", SysConstants.NO, SysConstants.YES, "密码必须包含特殊字符") { + PASSWORD_REQUIRE_SYMBOLS("密码是否必须包含特殊字符取值只能为是(%d)或否(%d)", GlobalConstants.Boolean.NO, GlobalConstants.Boolean.YES, "密码必须包含特殊字符") { @Override public void validateRange(int value, Map policyMap) { - ValidationUtils.throwIf(value != SysConstants.YES && value != SysConstants.NO, this.getDescription() - .formatted(SysConstants.YES, SysConstants.NO)); + ValidationUtils.throwIf(value != GlobalConstants.Boolean.YES && value != GlobalConstants.Boolean.NO, this + .getDescription() + .formatted(GlobalConstants.Boolean.YES, GlobalConstants.Boolean.NO)); } @Override public void validate(String password, int value, UserDO user) { - ValidationUtils.throwIf(value == SysConstants.YES && !ReUtil + ValidationUtils.throwIf(value == GlobalConstants.Boolean.YES && !ReUtil .isMatch(RegexConstants.SPECIAL_CHARACTER, password), this.getMsg()); } }, @@ -115,16 +116,17 @@ public enum PasswordPolicyEnum { /** * 密码是否允许包含用户名 */ - PASSWORD_ALLOW_CONTAIN_USERNAME("密码是否允许包含用户名取值只能为是(%d)或否(%d)", SysConstants.NO, SysConstants.YES, "密码不允许包含正反序用户名") { + PASSWORD_ALLOW_CONTAIN_USERNAME("密码是否允许包含用户名取值只能为是(%d)或否(%d)", GlobalConstants.Boolean.NO, GlobalConstants.Boolean.YES, "密码不允许包含正反序用户名") { @Override public void validateRange(int value, Map policyMap) { - ValidationUtils.throwIf(value != SysConstants.YES && value != SysConstants.NO, this.getDescription() - .formatted(SysConstants.YES, SysConstants.NO)); + ValidationUtils.throwIf(value != GlobalConstants.Boolean.YES && value != GlobalConstants.Boolean.NO, this + .getDescription() + .formatted(GlobalConstants.Boolean.YES, GlobalConstants.Boolean.NO)); } @Override public void validate(String password, int value, UserDO user) { - if (value <= SysConstants.NO) { + if (value <= GlobalConstants.Boolean.NO) { String username = user.getUsername(); ValidationUtils.throwIf(StrUtil.containsAnyIgnoreCase(password, username, StrUtil .reverse(username)), this.getMsg()); diff --git a/continew-system/src/main/java/top/continew/admin/system/model/entity/user/UserDO.java b/continew-system/src/main/java/top/continew/admin/system/model/entity/user/UserDO.java index 5b074d5d..13e1d67a 100644 --- a/continew-system/src/main/java/top/continew/admin/system/model/entity/user/UserDO.java +++ b/continew-system/src/main/java/top/continew/admin/system/model/entity/user/UserDO.java @@ -20,7 +20,7 @@ import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; -import top.continew.admin.common.base.model.entity.TenantBaseDO; +import top.continew.admin.common.base.model.entity.BaseDO; import top.continew.admin.common.enums.DisEnableStatusEnum; import top.continew.admin.common.enums.GenderEnum; import top.continew.starter.extension.crud.annotation.DictModel; @@ -39,7 +39,7 @@ import java.time.LocalDateTime; @Data @DictModel(labelKey = "nickname", extraKeys = {"username"}) @TableName("sys_user") -public class UserDO extends TenantBaseDO { +public class UserDO extends BaseDO { @Serial private static final long serialVersionUID = 1L; diff --git a/continew-system/src/main/java/top/continew/admin/system/model/query/MenuQuery.java b/continew-system/src/main/java/top/continew/admin/system/model/query/MenuQuery.java index 9fa4f8f8..49881c19 100644 --- a/continew-system/src/main/java/top/continew/admin/system/model/query/MenuQuery.java +++ b/continew-system/src/main/java/top/continew/admin/system/model/query/MenuQuery.java @@ -61,7 +61,7 @@ public class MenuQuery implements Serializable { /** * 排除的菜单 ID 列表 */ - @Schema(hidden = true, description = "菜单 ID 列表", example = "[9000]") + @Schema(hidden = true, description = "排除的菜单 ID 列表", example = "[9000]") @Query(columns = "id", type = QueryType.NOT_IN) private List excludeMenuIdList; } diff --git a/continew-system/src/main/java/top/continew/admin/system/model/query/RoleQuery.java b/continew-system/src/main/java/top/continew/admin/system/model/query/RoleQuery.java index 5c881ac2..d2bd4192 100644 --- a/continew-system/src/main/java/top/continew/admin/system/model/query/RoleQuery.java +++ b/continew-system/src/main/java/top/continew/admin/system/model/query/RoleQuery.java @@ -23,6 +23,7 @@ import top.continew.starter.data.enums.QueryType; import java.io.Serial; import java.io.Serializable; +import java.util.List; /** * 角色查询条件 @@ -43,4 +44,11 @@ public class RoleQuery implements Serializable { @Schema(description = "关键词", example = "测试人员") @Query(columns = {"name", "code", "description"}, type = QueryType.LIKE) private String description; + + /** + * 排除的编码列表 + */ + @Schema(description = "排除的编码列表", example = "[super_admin,tenant_admin]") + @Query(columns = "code", type = QueryType.NOT_IN) + private List excludeRoleCodes; } diff --git a/continew-system/src/main/java/top/continew/admin/system/model/resp/role/RoleUserResp.java b/continew-system/src/main/java/top/continew/admin/system/model/resp/role/RoleUserResp.java index dd4f3cbe..0925cb97 100644 --- a/continew-system/src/main/java/top/continew/admin/system/model/resp/role/RoleUserResp.java +++ b/continew-system/src/main/java/top/continew/admin/system/model/resp/role/RoleUserResp.java @@ -23,14 +23,12 @@ import cn.crane4j.core.executor.handler.OneToManyAssembleOperationHandler; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import top.continew.admin.common.constant.ContainerConstants; -import top.continew.admin.common.constant.SysConstants; import top.continew.admin.common.enums.DisEnableStatusEnum; import top.continew.admin.common.enums.GenderEnum; import java.io.Serial; import java.io.Serializable; import java.util.List; -import java.util.Objects; /** * 角色关联用户响应参数 @@ -126,6 +124,6 @@ public class RoleUserResp implements Serializable { private List roleNames; public Boolean getDisabled() { - return this.getIsSystem() && Objects.equals(roleId, SysConstants.SUPER_ROLE_ID); + return this.getIsSystem(); } } diff --git a/continew-system/src/main/java/top/continew/admin/system/service/RoleService.java b/continew-system/src/main/java/top/continew/admin/system/service/RoleService.java index 7e5b6036..20e742a1 100644 --- a/continew-system/src/main/java/top/continew/admin/system/service/RoleService.java +++ b/continew-system/src/main/java/top/continew/admin/system/service/RoleService.java @@ -85,12 +85,12 @@ public interface RoleService extends BaseService listByUserId(Long userId); /** - * 根据角色编码查询 + * 根据编码查询 ID * - * @param code 角色编码 - * @return 角色信息 + * @param code 编码 + * @return ID */ - RoleDO getByCode(String code); + Long getIdByCode(String code); /** * 根据角色名称查询 diff --git a/continew-system/src/main/java/top/continew/admin/system/service/impl/MenuServiceImpl.java b/continew-system/src/main/java/top/continew/admin/system/service/impl/MenuServiceImpl.java index 8ed1ef5d..228eea19 100644 --- a/continew-system/src/main/java/top/continew/admin/system/service/impl/MenuServiceImpl.java +++ b/continew-system/src/main/java/top/continew/admin/system/service/impl/MenuServiceImpl.java @@ -28,12 +28,12 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import top.continew.admin.common.base.service.BaseServiceImpl; import top.continew.admin.common.constant.CacheConstants; -import top.continew.admin.common.constant.SysConstants; import top.continew.admin.common.enums.DisEnableStatusEnum; +import top.continew.admin.common.enums.RoleCodeEnum; +import top.continew.admin.system.constant.SystemConstants; import top.continew.admin.system.enums.MenuTypeEnum; import top.continew.admin.system.mapper.MenuMapper; import top.continew.admin.system.model.entity.MenuDO; -import top.continew.admin.system.model.entity.RoleDO; import top.continew.admin.system.model.query.MenuQuery; import top.continew.admin.system.model.req.MenuReq; import top.continew.admin.system.model.resp.MenuResp; @@ -113,7 +113,7 @@ public class MenuServiceImpl extends BaseServiceImpl listByRoleId(Long roleId) { - if (SysConstants.SUPER_ROLE_ID.equals(roleId)) { + if (SystemConstants.SUPER_ADMIN_ROLE_ID.equals(roleId)) { return super.list(new MenuQuery(DisEnableStatusEnum.ENABLE), null); } List menuList = baseMapper.selectListByRoleId(roleId); @@ -124,9 +124,9 @@ public class MenuServiceImpl extends BaseServiceImpl listExcludeTenantMenu() { - RoleDO role = roleService.getByCode(SysConstants.TENANT_ADMIN_ROLE_CODE); + Long roleId = roleService.getIdByCode(RoleCodeEnum.TENANT_ADMIN.getCode()); List allMenuIdList = CollUtils.mapToList(super.list(), MenuDO::getId); - List menuIdList = CollUtils.mapToList(baseMapper.selectListByRoleId(role.getId()), MenuDO::getId); + List menuIdList = CollUtils.mapToList(baseMapper.selectListByRoleId(roleId), MenuDO::getId); return CollUtil.disjunction(allMenuIdList, menuIdList).stream().toList(); } diff --git a/continew-system/src/main/java/top/continew/admin/system/service/impl/RoleServiceImpl.java b/continew-system/src/main/java/top/continew/admin/system/service/impl/RoleServiceImpl.java index ab3143c4..af864421 100644 --- a/continew-system/src/main/java/top/continew/admin/system/service/impl/RoleServiceImpl.java +++ b/continew-system/src/main/java/top/continew/admin/system/service/impl/RoleServiceImpl.java @@ -26,11 +26,12 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import top.continew.admin.common.base.service.BaseServiceImpl; import top.continew.admin.common.constant.CacheConstants; -import top.continew.admin.common.constant.SysConstants; import top.continew.admin.common.context.RoleContext; import top.continew.admin.common.context.UserContext; import top.continew.admin.common.context.UserContextHolder; import top.continew.admin.common.enums.DataScopeEnum; +import top.continew.admin.common.enums.RoleCodeEnum; +import top.continew.admin.system.constant.SystemConstants; import top.continew.admin.system.mapper.RoleMapper; import top.continew.admin.system.model.entity.RoleDO; import top.continew.admin.system.model.query.RoleQuery; @@ -42,6 +43,8 @@ import top.continew.admin.system.model.resp.role.RoleResp; import top.continew.admin.system.service.*; import top.continew.starter.core.util.CollUtils; import top.continew.starter.core.util.validation.CheckUtils; +import top.continew.starter.extension.crud.model.query.SortQuery; +import top.continew.starter.extension.crud.model.resp.LabelValueResp; import java.util.Collections; import java.util.List; @@ -60,9 +63,10 @@ public class RoleServiceImpl extends BaseServiceImpl listDict(RoleQuery query, SortQuery sortQuery) { + query.setExcludeRoleCodes(RoleCodeEnum.getSuperRoleCodes()); + return super.listDict(query, sortQuery); + } + @Override @Transactional(rollbackFor = Exception.class) @CacheInvalidate(key = "#id", name = CacheConstants.ROLE_MENU_KEY_PREFIX) public void updatePermission(Long id, RoleUpdatePermissionReq req) { - super.getById(id); + RoleDO role = super.getById(id); + CheckUtils.throwIf(Boolean.TRUE.equals(role.getIsSystem()), "[{}] 是系统内置角色,不允许修改角色功能权限", role.getName()); // 保存角色和菜单关联 boolean isSaveMenuSuccess = roleMenuService.add(req.getMenuIds(), id); // 如果功能权限有变更,则更新在线用户权限信息 @@ -148,7 +159,8 @@ public class RoleServiceImpl extends BaseServiceImpl userIds) { - super.getById(id); + RoleDO role = super.getById(id); + CheckUtils.throwIf(Boolean.TRUE.equals(role.getIsSystem()), "[{}] 是系统内置角色,不允许分配角色给其他用户", role.getName()); // 保存用户和角色关联 userRoleService.assignRoleToUsers(id, userIds); // 更新用户上下文 @@ -172,8 +184,8 @@ public class RoleServiceImpl extends BaseServiceImpl listPermissionByUserId(Long userId) { Set roleCodeSet = this.listCodeByUserId(userId); // 超级管理员赋予全部权限 - if (roleCodeSet.contains(SysConstants.SUPER_ROLE_CODE)) { - return CollUtil.newHashSet(SysConstants.ALL_PERMISSION); + if (roleCodeSet.contains(RoleCodeEnum.SUPER_ADMIN.getCode())) { + return CollUtil.newHashSet(SystemConstants.ALL_PERMISSION); } return menuService.listPermissionByUserId(userId); } @@ -202,8 +214,8 @@ public class RoleServiceImpl extends BaseServiceImpl roleIds, Long userId) { + // 超级管理员和租户管理员角色不允许分配 + CheckUtils.throwIf(roleIds.contains(SystemConstants.SUPER_ADMIN_ROLE_ID), "不允许分配超级管理员角色"); + Set roleCodeSet = CollUtils.mapToSet(roleService.listByUserId(userId), RoleContext::getCode); + CheckUtils.throwIf(roleCodeSet.contains(RoleCodeEnum.TENANT_ADMIN.getCode()), "不允许分配系统管理员角色"); // 检查是否有变更 List oldRoleIdList = baseMapper.lambdaQuery() .select(UserRoleDO::getRoleId) @@ -81,8 +94,6 @@ public class UserRoleServiceImpl implements UserRoleService { if (CollUtil.isEmpty(CollUtil.disjunction(roleIds, oldRoleIdList))) { return false; } - CheckUtils.throwIf(SysConstants.SUPER_USER_ID.equals(userId) && !roleIds - .contains(SysConstants.SUPER_ROLE_ID), "不允许变更超管用户角色"); // 删除原有关联 baseMapper.lambdaUpdate().eq(UserRoleDO::getUserId, userId).remove(); // 保存最新关联 diff --git a/continew-system/src/main/java/top/continew/admin/system/service/impl/UserServiceImpl.java b/continew-system/src/main/java/top/continew/admin/system/service/impl/UserServiceImpl.java index 1eeac289..2a7db3ac 100644 --- a/continew-system/src/main/java/top/continew/admin/system/service/impl/UserServiceImpl.java +++ b/continew-system/src/main/java/top/continew/admin/system/service/impl/UserServiceImpl.java @@ -55,11 +55,11 @@ import org.springframework.web.multipart.MultipartFile; import top.continew.admin.auth.service.OnlineUserService; import top.continew.admin.common.base.service.BaseServiceImpl; import top.continew.admin.common.constant.CacheConstants; -import top.continew.admin.common.constant.SysConstants; import top.continew.admin.common.context.UserContext; import top.continew.admin.common.context.UserContextHolder; import top.continew.admin.common.enums.DisEnableStatusEnum; import top.continew.admin.common.enums.GenderEnum; +import top.continew.admin.system.constant.SystemConstants; import top.continew.admin.system.enums.OptionCategoryEnum; import top.continew.admin.system.mapper.user.UserMapper; import top.continew.admin.system.model.entity.DeptDO; @@ -510,7 +510,7 @@ public class UserServiceImpl extends BaseServiceImpl { + .and(deptId != null && !SystemConstants.SUPER_DEPT_ID.equals(deptId), q -> { List deptIdList = CollUtils.mapToList(deptService.listChildren(deptId), DeptDO::getId); deptIdList.add(deptId); q.in("t1.dept_id", deptIdList);