mirror of
https://github.com/continew-org/continew-admin.git
synced 2025-09-08 12:57:13 +08:00
refactor: 梳理用户和角色体系,内置角色:超级管理员、租户管理员(系统管理员),且内置用户和角色不允许变更及分配
This commit is contained in:
@@ -61,6 +61,15 @@ public class CrudApiPermissionPrefixCache {
|
||||
PERMISSION_PREFIX_CACHE.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有缓存
|
||||
*
|
||||
* @return 所有缓存
|
||||
*/
|
||||
public static Map<Class<?>, String> getAll() {
|
||||
return PERMISSION_PREFIX_CACHE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析权限前缀(解析路径获取模块名和资源名)
|
||||
*
|
||||
|
@@ -34,7 +34,7 @@ public class DefaultDataPermissionUserDataProvider implements DataPermissionUser
|
||||
|
||||
@Override
|
||||
public boolean isFilter() {
|
||||
return !UserContextHolder.isAdmin();
|
||||
return !UserContextHolder.isSuperAdminUser() && !UserContextHolder.isTenantAdminUser();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -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() {
|
||||
}
|
||||
}
|
@@ -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() {
|
||||
}
|
||||
}
|
@@ -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<RoleContext> 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());
|
||||
}
|
||||
}
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
@@ -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<String> 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);
|
||||
}
|
||||
}
|
@@ -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<TenantMapper, TenantDO, T
|
||||
}));
|
||||
// 租户管理员:新增菜单
|
||||
tenantIdList.forEach(tenantId -> TenantUtils.execute(tenantId, () -> {
|
||||
Long roleId = roleApi.getIdByCode(SysConstants.TENANT_ADMIN_ROLE_CODE);
|
||||
Long roleId = roleApi.getIdByCode(RoleCodeEnum.TENANT_ADMIN.getCode());
|
||||
List<Long> oldMenuIdList = roleMenuApi.listMenuIdByRoleIds(List.of(roleId));
|
||||
Collection<Long> addMenuIdList = CollUtil.disjunction(newMenuIds, oldMenuIdList);
|
||||
if (CollUtil.isNotEmpty(addMenuIdList)) {
|
||||
|
@@ -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() + "登录");
|
||||
// 解析账号登录用户为操作人
|
||||
|
@@ -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());
|
||||
}
|
||||
}
|
||||
|
@@ -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();
|
||||
|
@@ -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<Long> USER_FLAG = List
|
||||
.of(1L, 547889293968801822L, 547889293968801823L, 547889293968801824L, 547889293968801825L,
|
||||
547889293968801826L, 547889293968801827L, 547889293968801828L, 547889293968801829L,
|
||||
547889293968801830L, 547889293968801831L, 547889293968801832L, 547889293968801833L, 547889293968801834L);
|
||||
private static final List<Long> 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<Long> ROLE_FLAG = List.of(1L, 2L, 3L, 547888897925840927L, 547888897925840928L);
|
||||
private static final Long DEPT_FLAG = 547887852587843611L;
|
||||
|
||||
/**
|
||||
|
@@ -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:
|
||||
|
@@ -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()),
|
||||
|
@@ -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()),
|
||||
|
@@ -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() {
|
||||
}
|
||||
}
|
@@ -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<AccountLoginReq> {
|
||||
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<AccountLoginReq> {
|
||||
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;
|
||||
}
|
||||
// 检测是否已被锁定
|
||||
|
@@ -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<SocialLoginReq> {
|
||||
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);
|
||||
|
@@ -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<MenuResp> 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())));
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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("系统初始用户");
|
||||
|
@@ -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"));
|
||||
}
|
||||
|
@@ -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() {
|
||||
}
|
||||
}
|
@@ -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<String, String> 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<String, String> 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<String, String> 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());
|
||||
|
@@ -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;
|
||||
|
@@ -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<Long> excludeMenuIdList;
|
||||
}
|
||||
|
@@ -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<String> excludeRoleCodes;
|
||||
}
|
||||
|
@@ -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<String> roleNames;
|
||||
|
||||
public Boolean getDisabled() {
|
||||
return this.getIsSystem() && Objects.equals(roleId, SysConstants.SUPER_ROLE_ID);
|
||||
return this.getIsSystem();
|
||||
}
|
||||
}
|
||||
|
@@ -85,12 +85,12 @@ public interface RoleService extends BaseService<RoleResp, RoleDetailResp, RoleQ
|
||||
Set<RoleContext> listByUserId(Long userId);
|
||||
|
||||
/**
|
||||
* 根据角色编码查询
|
||||
* 根据编码查询 ID
|
||||
*
|
||||
* @param code 角色编码
|
||||
* @return 角色信息
|
||||
* @param code 编码
|
||||
* @return ID
|
||||
*/
|
||||
RoleDO getByCode(String code);
|
||||
Long getIdByCode(String code);
|
||||
|
||||
/**
|
||||
* 根据角色名称查询
|
||||
|
@@ -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<MenuMapper, MenuDO, MenuRes
|
||||
@Override
|
||||
@Cached(key = "#roleId", name = CacheConstants.ROLE_MENU_KEY_PREFIX)
|
||||
public List<MenuResp> 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<MenuDO> menuList = baseMapper.selectListByRoleId(roleId);
|
||||
@@ -124,9 +124,9 @@ public class MenuServiceImpl extends BaseServiceImpl<MenuMapper, MenuDO, MenuRes
|
||||
|
||||
@Override
|
||||
public List<Long> listExcludeTenantMenu() {
|
||||
RoleDO role = roleService.getByCode(SysConstants.TENANT_ADMIN_ROLE_CODE);
|
||||
Long roleId = roleService.getIdByCode(RoleCodeEnum.TENANT_ADMIN.getCode());
|
||||
List<Long> allMenuIdList = CollUtils.mapToList(super.list(), MenuDO::getId);
|
||||
List<Long> menuIdList = CollUtils.mapToList(baseMapper.selectListByRoleId(role.getId()), MenuDO::getId);
|
||||
List<Long> menuIdList = CollUtils.mapToList(baseMapper.selectListByRoleId(roleId), MenuDO::getId);
|
||||
return CollUtil.disjunction(allMenuIdList, menuIdList).stream().toList();
|
||||
}
|
||||
|
||||
|
@@ -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<RoleMapper, RoleDO, RoleRes
|
||||
|
||||
@Resource
|
||||
private MenuService menuService;
|
||||
@Resource
|
||||
private UserRoleService userRoleService;
|
||||
private final RoleMenuService roleMenuService;
|
||||
private final RoleDeptService roleDeptService;
|
||||
private final UserRoleService userRoleService;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@@ -70,8 +74,8 @@ public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleRes
|
||||
this.checkNameRepeat(req.getName(), null);
|
||||
String code = req.getCode();
|
||||
this.checkCodeRepeat(code, null);
|
||||
// 防止租户添加超管
|
||||
CheckUtils.throwIfEqual(SysConstants.SUPER_ROLE_CODE, code, "编码 [{}] 禁止使用", code);
|
||||
// 防止租户添加超级管理员
|
||||
CheckUtils.throwIfEqual(RoleCodeEnum.SUPER_ADMIN.getCode(), code, "编码 [{}] 禁止使用", code);
|
||||
// 新增信息
|
||||
Long roleId = super.create(req);
|
||||
// 保存角色和部门关联
|
||||
@@ -91,7 +95,7 @@ public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleRes
|
||||
}
|
||||
// 更新信息
|
||||
super.update(req, id);
|
||||
if (SysConstants.SUPER_ROLE_CODE.equals(req.getCode())) {
|
||||
if (RoleCodeEnum.isSuperRoleCode(req.getCode())) {
|
||||
return;
|
||||
}
|
||||
// 保存角色和部门关联
|
||||
@@ -129,11 +133,18 @@ public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleRes
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<LabelValueResp> 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<RoleMapper, RoleDO, RoleRes
|
||||
|
||||
@Override
|
||||
public void assignToUsers(Long id, List<Long> 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<RoleMapper, RoleDO, RoleRes
|
||||
public Set<String> listPermissionByUserId(Long userId) {
|
||||
Set<String> 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<RoleMapper, RoleDO, RoleRes
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoleDO getByCode(String code) {
|
||||
return baseMapper.lambdaQuery().eq(RoleDO::getCode, code).one();
|
||||
public Long getIdByCode(String code) {
|
||||
return baseMapper.lambdaQuery().eq(RoleDO::getCode, code).oneOpt().map(RoleDO::getId).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -22,14 +22,19 @@ import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import top.continew.admin.common.constant.SysConstants;
|
||||
import top.continew.admin.common.context.RoleContext;
|
||||
import top.continew.admin.common.enums.RoleCodeEnum;
|
||||
import top.continew.admin.system.constant.SystemConstants;
|
||||
import top.continew.admin.system.mapper.UserRoleMapper;
|
||||
import top.continew.admin.system.model.entity.UserRoleDO;
|
||||
import top.continew.admin.system.model.query.RoleUserQuery;
|
||||
import top.continew.admin.system.model.resp.role.RoleUserResp;
|
||||
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.validation.CheckUtils;
|
||||
@@ -38,6 +43,7 @@ import top.continew.starter.extension.crud.model.query.PageQuery;
|
||||
import top.continew.starter.extension.crud.model.resp.PageResp;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 用户和角色业务实现
|
||||
@@ -50,6 +56,9 @@ import java.util.List;
|
||||
public class UserRoleServiceImpl implements UserRoleService {
|
||||
|
||||
private final UserRoleMapper baseMapper;
|
||||
@Lazy
|
||||
@Resource
|
||||
private RoleService roleService;
|
||||
|
||||
@Override
|
||||
@AutoOperate(type = RoleUserResp.class, on = "list")
|
||||
@@ -70,6 +79,10 @@ public class UserRoleServiceImpl implements UserRoleService {
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean assignRolesToUser(List<Long> roleIds, Long userId) {
|
||||
// 超级管理员和租户管理员角色不允许分配
|
||||
CheckUtils.throwIf(roleIds.contains(SystemConstants.SUPER_ADMIN_ROLE_ID), "不允许分配超级管理员角色");
|
||||
Set<String> roleCodeSet = CollUtils.mapToSet(roleService.listByUserId(userId), RoleContext::getCode);
|
||||
CheckUtils.throwIf(roleCodeSet.contains(RoleCodeEnum.TENANT_ADMIN.getCode()), "不允许分配系统管理员角色");
|
||||
// 检查是否有变更
|
||||
List<Long> 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();
|
||||
// 保存最新关联
|
||||
|
@@ -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<UserMapper, UserDO, UserRes
|
||||
.eq(status != null, "t1.status", status)
|
||||
.between(CollUtil.isNotEmpty(createTimeList), "t1.create_time", CollUtil.getFirst(createTimeList), CollUtil
|
||||
.getLast(createTimeList))
|
||||
.and(deptId != null && !SysConstants.SUPER_DEPT_ID.equals(deptId), q -> {
|
||||
.and(deptId != null && !SystemConstants.SUPER_DEPT_ID.equals(deptId), q -> {
|
||||
List<Long> deptIdList = CollUtils.mapToList(deptService.listChildren(deptId), DeptDO::getId);
|
||||
deptIdList.add(deptId);
|
||||
q.in("t1.dept_id", deptIdList);
|
||||
|
Reference in New Issue
Block a user