diff --git a/cf-framework/cf-spring-boot-starter-security/src/main/java/com/cf/imes/framework/security/core/util/SecurityFrameworkUtils.java b/cf-framework/cf-spring-boot-starter-security/src/main/java/com/cf/imes/framework/security/core/util/SecurityFrameworkUtils.java index 07c8ee7d6..7a711ff96 100644 --- a/cf-framework/cf-spring-boot-starter-security/src/main/java/com/cf/imes/framework/security/core/util/SecurityFrameworkUtils.java +++ b/cf-framework/cf-spring-boot-starter-security/src/main/java/com/cf/imes/framework/security/core/util/SecurityFrameworkUtils.java @@ -1,6 +1,7 @@ package com.cf.imes.framework.security.core.util; import cn.hutool.core.util.ObjectUtil; +import com.cf.imes.framework.common.enums.UserTypeEnum; import com.cf.imes.framework.common.exception.ServiceException; import com.cf.imes.framework.common.exception.enums.GlobalErrorCodeConstants; import com.cf.imes.framework.security.core.LoginUser; @@ -15,6 +16,7 @@ import org.springframework.util.StringUtils; import jakarta.servlet.http.HttpServletRequest; import java.util.Collections; +import java.util.Objects; /** * 安全服务工具类 @@ -30,6 +32,8 @@ public class SecurityFrameworkUtils { public static final String LOGIN_USER_HEADER = "login-user"; + public static final Long CF_ORGANID = 1L; + private SecurityFrameworkUtils() {} /** @@ -143,4 +147,23 @@ public class SecurityFrameworkUtils { LoginUser loginUser = getLoginUser(); return ObjectUtil.isNotNull(loginUser) && loginUser.getIsSupAdmin(); } + + /** + * 当前用户是否登录管理端 + * + * @return + */ + public static boolean isManageEndPoint() { + LoginUser loginUser = getLoginUser(); + return Objects.equals(loginUser.getUserType(), UserTypeEnum.ADMIN.getValue()) && loginUser.getIsSupAdmin(); + } + + /** + * 当前用户是否晨丰组织 + * @return + */ + public static boolean isCfOrg(Long... organIds) { + Long organId = (organIds != null && organIds.length > 0) ? organIds[0] : getUserOrganId(); + return Objects.equals(organId, CF_ORGANID); + } } diff --git a/cf-module-report/cf-module-report-biz/src/main/resources/application.yaml b/cf-module-report/cf-module-report-biz/src/main/resources/application.yaml index f027e6c56..822eeb164 100644 --- a/cf-module-report/cf-module-report-biz/src/main/resources/application.yaml +++ b/cf-module-report/cf-module-report-biz/src/main/resources/application.yaml @@ -3,7 +3,7 @@ spring: name: report-server profiles: - active: test + active: local main: allow-circular-references: true # 允许循环依赖,因为项目是三层架构,无法避免这个情况。 diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java index 70204c967..adcbfdcc4 100644 --- a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java @@ -14,11 +14,9 @@ public class ErrorCodeConstants { public static final ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1_002_000_001, "登录失败,账号被禁用"); public static final ErrorCode AUTH_LOGIN_CAPTCHA_CODE_ERROR = new ErrorCode(1_002_000_004, "验证码不正确,原因:{}"); public static final ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1_002_000_005, "未绑定账号,需要进行绑定"); - public static final ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1_002_000_006, "Token 已经过期"); - public static final ErrorCode AUTH_MOBILE_NOT_EXISTS = new ErrorCode(1_002_000_007, "手机号不存在"); - public static final ErrorCode AUTH_MOBILE_NO_CHANGE = new ErrorCode(1_002_000_008, "手机号未发生改变,无需修改"); - public static final ErrorCode AUTH_LOGIN_GEO_UNCORRECT = new ErrorCode(1_002_000_009, "登录失败,请前往机构登记地址登录系统"); - public static final ErrorCode AUTH_LOGIN_ORG_GEO_EMPTY = new ErrorCode(1_002_000_010, "当前组织地址未登记,请联系组织管理员"); + public static final ErrorCode AUTH_MOBILE_NOT_EXISTS = new ErrorCode(1_002_000_006, "手机号不存在"); + public static final ErrorCode AUTH_MOBILE_NO_CHANGE = new ErrorCode(1_002_000_007, "手机号未发生改变,无需修改"); + public static final ErrorCode AUTH_MANAGEENDPOINT_LOGIN_PERMISSION_ERROR = new ErrorCode(1_002_000_008, "登录失败,管理端账号不存在"); // ========== 菜单模块 1-002-001-000 ========== public static final ErrorCode MENU_NAME_DUPLICATE = new ErrorCode(1_002_001_000, "已经存在该名字的菜单"); @@ -27,6 +25,7 @@ public class ErrorCodeConstants { public static final ErrorCode MENU_NOT_EXISTS = new ErrorCode(1_002_001_003, "菜单不存在"); public static final ErrorCode MENU_EXISTS_CHILDREN = new ErrorCode(1_002_001_004, "存在子菜单,无法删除"); public static final ErrorCode MENU_PARENT_NOT_DIR_OR_MENU = new ErrorCode(1_002_001_005, "父菜单的类型必须是目录或者菜单"); + public static final ErrorCode MANAGEMENT_MENU_OPERATION_PERMISSION_ERROR = new ErrorCode(1_002_001_006, "管理端菜单操作权限不足"); // ========== 角色模块 1-002-002-000 ========== public static final ErrorCode ROLE_NOT_EXISTS = new ErrorCode(1_002_002_000, "角色不存在"); @@ -34,7 +33,7 @@ public class ErrorCodeConstants { public static final ErrorCode ROLE_CODE_DUPLICATE = new ErrorCode(1_002_002_002, "已经存在编码为【{}】的角色"); public static final ErrorCode ROLE_CAN_NOT_UPDATE_SYSTEM_TYPE_ROLE = new ErrorCode(1_002_002_003, "不能操作类型为系统内置的角色"); public static final ErrorCode ROLE_IS_DISABLE = new ErrorCode(1_002_002_004, "名字为【{}】的角色已被禁用"); - public static final ErrorCode ROLE_ADMIN_CODE_ERROR = new ErrorCode(1_002_002_005, "编码【{}】不能使用"); + public static final ErrorCode ROLE_ADMIN_CODE_ERROR = new ErrorCode(1_002_002_005, "编码【{}】不能使用"); public static final ErrorCode ROLE_ME_ERROR = new ErrorCode(1_002_002_006, "不可为自身分配角色"); public static final ErrorCode ROLE_NOT_SUPERADMIN_NO_ORGAN_ID_OPER_ERROR = new ErrorCode(1_002_002_007, "非超管分配权限"); public static final ErrorCode BUILDIN_ROLE_MODIFY_PERMISSION_ERROR = new ErrorCode(1_002_002_008, "修改内置角色下菜单权限的权限不足"); diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/permission/MenuSourceTypeEnum.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/permission/MenuSourceTypeEnum.java new file mode 100644 index 000000000..d0029c2c1 --- /dev/null +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/permission/MenuSourceTypeEnum.java @@ -0,0 +1,30 @@ +package com.cf.imes.module.system.enums.permission; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 菜单来源类型枚举类 + * + * @author 晨丰科技 + */ +@Getter +@AllArgsConstructor +public enum MenuSourceTypeEnum { + + /** + * 生产端 + */ + PRODUCTION(1), + + /** + * 管理端 + */ + MANAGEMENT(2); + + /** + * 类型 + */ + private final Integer type; + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/auth/AuthController.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/auth/AuthController.java index f0a3b768b..bcebf2a77 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/auth/AuthController.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/auth/AuthController.java @@ -43,7 +43,6 @@ import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.ibatis.annotations.Param; -import org.springframework.beans.factory.annotation.Value; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -92,18 +91,20 @@ public class AuthController { @Resource private IPQueryService ipQueryService; - /** - * ip服务开关,默认为 false不开启 - */ - @Value("${chenfeng.ipquery.enable:false}") - private boolean ipQueryEnable; + @PostMapping("/manage/login") + @PermitAll + @Operation(summary = "使用账号密码登录") + @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 + public CommonResult manageEndPointlogin(@Valid @RequestBody AuthLoginReqVO reqVO) { + return success(authService.login(reqVO, true)); + } @PostMapping("/login") @PermitAll @Operation(summary = "使用账号密码登录") @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 public CommonResult login(@Valid @RequestBody AuthLoginReqVO reqVO) { - return success(authService.login(reqVO)); + return success(authService.login(reqVO, false)); } @GetMapping("/login/check") @@ -177,7 +178,12 @@ public class AuthController { // 1.3 获得菜单列表 Set menuIds = permissionService.getRoleMenuListByRoleId2(convertSet(roles, RoleDO::getId), loginUser.getOrganId()); - List menuList = menuService.getMenuList1(menuIds); + List menuList; + if(SecurityFrameworkUtils.isManageEndPoint()){ + menuList = menuService.getManageEndPointMenuList(menuIds); + } else { + menuList = menuService.getCustomEndPointMenuList(menuIds); + } menuList.removeIf(menu -> !CommonStatusEnum.ENABLE.getStatus().equals(menu.getStatus())); // 移除禁用的菜单 // 2. 拼接结果返回 diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/dept/DeptController.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/dept/DeptController.java index 1b6117bf6..040b373f5 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/dept/DeptController.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/dept/DeptController.java @@ -19,7 +19,10 @@ import org.springframework.web.bind.annotation.*; import jakarta.annotation.Resource; import jakarta.validation.Valid; + +import java.util.ArrayList; import java.util.List; +import java.util.Objects; import static com.cf.imes.framework.common.pojo.CommonResult.success; @@ -65,9 +68,9 @@ public class DeptController { return success(BeanUtils.toBean(list, DeptRespVO.class)); } - @GetMapping(value = {"/list-all-simple", "/simple-list"}) + @GetMapping(value = "/list-all-simple") @Operation(summary = "获取部门精简信息列表", description = "只包含被开启的部门,主要用于前端的下拉选项") - public CommonResult> getSimpleDeptList(@Valid DeptListReqVO reqVO) { + public CommonResult> getAllSimpleDeptList(@Valid DeptListReqVO reqVO) { // 有效部门的请求,传入organid就查对应的,没有就查登录人下的 DeptListReqVO efficDeptReqVO = new DeptListReqVO().setStatus(CommonStatusEnum.ENABLE.getStatus()); if (ObjectUtils.allNotNull(reqVO, reqVO.getOrganId())) { @@ -77,6 +80,16 @@ public class DeptController { return success(BeanUtils.toBean(deptService.removeUnowndDept(list), DeptSimpleRespVO.class)); } + @GetMapping(value = "/simple-list") + @Operation(summary = "获取部门精简信息列表", description = "只包含被开启的部门,主要用于前端的下拉选项") + public CommonResult> getSimpleDeptList(@Valid DeptListReqVO reqVO) { + if (Objects.isNull(reqVO.getOrganId())) { + return success(new ArrayList<>()); + } + List list = deptService.getDeptList(reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus())); + return success(BeanUtils.toBean(deptService.removeUnowndDept(list), DeptSimpleRespVO.class)); + } + @GetMapping("/get") @Operation(summary = "获得部门信息") @Parameter(name = "id", description = "编号", required = true, example = "1024") diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/permission/MenuController.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/permission/MenuController.java index 43f332960..8c9e3eee8 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/permission/MenuController.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/permission/MenuController.java @@ -77,6 +77,36 @@ public class MenuController { return success(true); } + @GetMapping("/custom/list") + @Operation(summary = "获取菜单列表", description = "用于【菜单管理】界面") + @PreAuthorize("@ss.hasPermission('system:permission:assign-role-menu')") + public CommonResult> getCustomMenuList() { + List list; + LoginUser loginUser = getLoginUser(); + if (ObjectUtil.isNull(loginUser)) { + throw new ServiceException(GlobalErrorCodeConstants.UNAUTHORIZED); + } + AdminUserDO user = userService.getUser(loginUser.getId()); + if (user == null) { + return success(new ArrayList<>()); + } + // 获取登录用户所属角色 + Set roleIds = permissionService.getUserRoleIdListByUserId(loginUser.getId()); + if (CollUtil.isEmpty(roleIds)) { + return success(new ArrayList<>()); + } + // 查询角色并过滤无效的 + List roles = roleService.getRoleList1(roleIds); + roles.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色 + // 查询角色拥有权限的菜单id + Set menuIds = permissionService.getRoleMenuListByRoleId2(convertSet(roles, RoleDO::getId), loginUser.getOrganId()); + list = menuService.getCustomEndPointMenuList(menuIds); + list.removeIf(menu -> !CommonStatusEnum.ENABLE.getStatus().equals(menu.getStatus())); // 移除禁用的菜单 + + list.sort(Comparator.comparing(MenuDO::getSort)); + return success(BeanUtils.toBean(list, MenuRespVO.class)); + } + @GetMapping("/list") @Operation(summary = "获取菜单列表", description = "用于【菜单管理】界面") @PreAuthorize("@ss.hasAnyPermissions('system:menu:query','base:permission:assign-role-menu','system:permission:assign-role-menu')") diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/permission/vo/menu/MenuListReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/permission/vo/menu/MenuListReqVO.java index 420efaa1c..3d21667df 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/permission/vo/menu/MenuListReqVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/permission/vo/menu/MenuListReqVO.java @@ -21,4 +21,8 @@ public class MenuListReqVO { @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1") @CommonStatus private Integer visiable; + + @Schema(description = "菜单来源,参见 MenuSourceTypeEnum 枚举类", example = "1") + @CommonStatus + private Integer sourceType; } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/permission/vo/menu/MenuRespVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/permission/vo/menu/MenuRespVO.java index 79665a7b3..8ec986a5c 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/permission/vo/menu/MenuRespVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/permission/vo/menu/MenuRespVO.java @@ -69,4 +69,6 @@ public class MenuRespVO { @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式") private LocalDateTime createTime; + @Schema(description = "菜单来源类型", example = "1") + private Integer sourceType; } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/permission/vo/menu/MenuSaveVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/permission/vo/menu/MenuSaveVO.java index 0b6f2ce76..6e3bbcc3b 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/permission/vo/menu/MenuSaveVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/permission/vo/menu/MenuSaveVO.java @@ -2,6 +2,7 @@ package com.cf.imes.module.system.controller.admin.permission.vo.menu; import com.cf.imes.framework.common.validation.NumberValid; import com.cf.imes.module.system.validation.common.CommonStatus; +import com.cf.imes.module.system.validation.menu.MenuSourceTypeValid; import com.cf.imes.module.system.validation.menu.MenuTypeValid; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -74,4 +75,9 @@ public class MenuSaveVO { @Schema(description = "权限功能描述") private String description; + @Schema(description = "菜单来源类型 ,见 MenuSourceTypeValid 枚举",example = "1") + @NotNull + @MenuSourceTypeValid + private Integer sourceType; + } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/permission/MenuDO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/permission/MenuDO.java index 959a0bc06..f7b2efa12 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/permission/MenuDO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/permission/MenuDO.java @@ -112,5 +112,8 @@ public class MenuDO extends BaseDO { */ private String description; - + /** + * 来源类型 + */ + private Integer sourceType; } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/user/AdminUserDO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/user/AdminUserDO.java index c4b0c681f..8e8b88a85 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/user/AdminUserDO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/user/AdminUserDO.java @@ -2,6 +2,7 @@ package com.cf.imes.module.system.dal.dataobject.user; import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.cf.imes.framework.common.enums.CommonStatusEnum; +import com.cf.imes.framework.common.enums.UserTypeEnum; import com.cf.imes.framework.mybatis.core.type.JsonLongSetTypeHandler; import com.cf.imes.framework.organ.core.db.OrganBaseDO; import com.cf.imes.module.system.enums.common.SexEnum; @@ -117,4 +118,16 @@ public class AdminUserDO extends OrganBaseDO { */ @TableField(exist = false) private String grayDefaultVersion; + + /** + * 是否超级管理员 + */ + @TableField(exist = false) + private boolean isSuperAdmin; + + /** + * 用户类型 + */ + @TableField(exist = false) + private UserTypeEnum userType; } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/permission/MenuMapper.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/permission/MenuMapper.java index 7e3d39cff..019b8ca6b 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/permission/MenuMapper.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/permission/MenuMapper.java @@ -23,7 +23,8 @@ public interface MenuMapper extends BaseMapperX { return selectList(new LambdaQueryWrapperX() .likeIfPresent(MenuDO::getName, reqVO.getName()) .eqIfPresent(MenuDO::getStatus, reqVO.getStatus()) - .eqIfPresent(MenuDO::getVisible, reqVO.getVisiable())); + .eqIfPresent(MenuDO::getVisible, reqVO.getVisiable()) + .eqIfPresent(MenuDO::getSourceType, reqVO.getSourceType())); } default List selectListByPermission(String permission) { diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/user/AdminUserMapper.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/user/AdminUserMapper.java index d3654042f..5d0a57bea 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/user/AdminUserMapper.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/user/AdminUserMapper.java @@ -70,10 +70,11 @@ public interface AdminUserMapper extends BaseMapperX { LambdaQueryWrapperX lambdaQueryWrapperX = new LambdaQueryWrapperX<>(); LoginUser loginUser = SecurityFrameworkUtils.getLoginUser(); assert loginUser != null; - Boolean isSupAdmin = loginUser.getIsSupAdmin(); - if(isSupAdmin && !Objects.isNull(reqVO.getOrganId())) { - lambdaQueryWrapperX.eqIfPresent(AdminUserDO::getOrganId, reqVO.getOrganId()); - }else{ + if (SecurityFrameworkUtils.isCfOrg()) { + if (!Objects.isNull(reqVO.getOrganId())) { + lambdaQueryWrapperX.eqIfPresent(AdminUserDO::getOrganId, reqVO.getOrganId()); + } + } else { lambdaQueryWrapperX.eqIfPresent(AdminUserDO::getOrganId, loginUser.getOrganId()); } return selectPage(reqVO, lambdaQueryWrapperX diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/auth/AdminAuthService.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/auth/AdminAuthService.java index a0dfa5527..f94239cdd 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/auth/AdminAuthService.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/auth/AdminAuthService.java @@ -31,9 +31,10 @@ public interface AdminAuthService { * 账号登录 * * @param reqVO 登录信息 + * @param isManageEndPoint 是否为管理端登录 * @return 登录结果 */ - AuthLoginRespVO login(@Valid AuthLoginReqVO reqVO); + AuthLoginRespVO login(@Valid AuthLoginReqVO reqVO, boolean isManageEndPoint); /** * 登录校验 diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/auth/AdminAuthServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/auth/AdminAuthServiceImpl.java index 4fb384db8..bf51cc6d6 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/auth/AdminAuthServiceImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/auth/AdminAuthServiceImpl.java @@ -6,6 +6,7 @@ import com.anji.captcha.model.vo.CaptchaVO; import com.anji.captcha.service.CaptchaService; import com.cf.imes.framework.common.enums.CommonStatusEnum; import com.cf.imes.framework.common.enums.UserTypeEnum; +import com.cf.imes.framework.common.exception.ServiceException; import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil; import com.cf.imes.framework.common.util.monitor.TracerUtils; import com.cf.imes.framework.common.util.servlet.ServletUtils; @@ -14,6 +15,8 @@ import com.cf.imes.framework.ip.core.service.IPQueryService; import com.cf.imes.framework.ip.core.service.dto.IPQueryDataRespDTO; import com.cf.imes.framework.organ.core.context.OrganContextHolder; import com.cf.imes.framework.organ.core.service.OrganFrameworkService; +import com.cf.imes.framework.security.core.service.SecurityFrameworkService; +import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; import com.cf.imes.module.system.api.logger.dto.LoginLogCreateReqDTO; import com.cf.imes.module.system.api.sms.SmsCodeApi; import com.cf.imes.module.system.api.social.dto.SocialUserRespDTO; @@ -97,6 +100,9 @@ public class AdminAuthServiceImpl implements AdminAuthService { @Autowired private TransactionTemplate transactionTemplate; + @Autowired + private SecurityFrameworkService securityFrameworkService; + /** * 验证码的开关,默认为 true */ @@ -118,7 +124,7 @@ public class AdminAuthServiceImpl implements AdminAuthService { AdminUserDO user = userService.getUserUniqueByUserName(username); // 校验用户是否存在 if (user == null) { - createLoginLog(null, username, null, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS); + createLoginLog(null, username, null, null, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS); throw ServiceExceptionUtil.exception(ErrorCodeConstants.AUTH_LOGIN_BAD_CREDENTIALS); } Long organId = user.getOrganId(); @@ -129,12 +135,12 @@ public class AdminAuthServiceImpl implements AdminAuthService { organFrameworkService.validDept(user.getDeptId()); // 校验密码 if (!userService.isPasswordMatch(password, user.getPassword())) { - createLoginLog(user.getId(), username, organId, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS); + createLoginLog(user.getId(), username, null, organId, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS); throw ServiceExceptionUtil.exception(ErrorCodeConstants.AUTH_LOGIN_BAD_CREDENTIALS); } // 校验是否禁用 if (CommonStatusEnum.isDisable(user.getStatus())) { - createLoginLog(user.getId(), username, organId, logTypeEnum, LoginResultEnum.USER_DISABLED); + createLoginLog(user.getId(), username, null, organId, logTypeEnum, LoginResultEnum.USER_DISABLED); throw ServiceExceptionUtil.exception(ErrorCodeConstants.AUTH_LOGIN_USER_DISABLED); } return user; @@ -142,12 +148,25 @@ public class AdminAuthServiceImpl implements AdminAuthService { @Override - public AuthLoginRespVO login(AuthLoginReqVO reqVO) { + public AuthLoginRespVO login(AuthLoginReqVO reqVO, boolean isManageEndPoint) { // 校验验证码 validateCaptcha(reqVO); // 使用账号密码,进行登录 AdminUserDO user = authenticate(reqVO); + Long userId = user.getId(); + + // 管理端只允许超管登录 + boolean isSuperAdmin = securityFrameworkService.hasAnyRoles(userId, "super_admin"); + user.setSuperAdmin(isSuperAdmin); + if (isSuperAdmin || SecurityFrameworkUtils.isCfOrg(user.getOrganId())) { + user.setUserType(isManageEndPoint ? UserTypeEnum.ADMIN : UserTypeEnum.MEMBER); + } else { + if (isManageEndPoint) { + throw new ServiceException(ErrorCodeConstants.AUTH_MANAGEENDPOINT_LOGIN_PERMISSION_ERROR); + } + user.setUserType(UserTypeEnum.MEMBER); + } Long organId = user.getOrganId(); OrganizationDO organ = organService.getOrgan(organId); @@ -173,7 +192,7 @@ public class AdminAuthServiceImpl implements AdminAuthService { AdminUserDO user = userService.getUserUniqueByUserName(mobile); // 校验用户是否存在 if (user == null) { - createLoginLog(null, mobile, null, LoginLogTypeEnum.LOGIN_USERNAME, LoginResultEnum.BAD_CREDENTIALS); + createLoginLog(null, mobile, null, null, LoginLogTypeEnum.LOGIN_USERNAME, LoginResultEnum.BAD_CREDENTIALS); return false; } if (StringUtils.isEmpty(user.getPassword())) { @@ -189,7 +208,7 @@ public class AdminAuthServiceImpl implements AdminAuthService { AdminUserDO user = userService.getUserUniqueByUserName(mobile); // 校验用户是否存在 if (user == null) { - createLoginLog(null, mobile, null, LoginLogTypeEnum.LOGIN_USERNAME, LoginResultEnum.BAD_CREDENTIALS); + createLoginLog(null, mobile, null, null, LoginLogTypeEnum.LOGIN_USERNAME, LoginResultEnum.BAD_CREDENTIALS); return false; } // 校验验证码正确性 @@ -228,7 +247,7 @@ public class AdminAuthServiceImpl implements AdminAuthService { return createTokenAfterLoginSuccess(user, reqVO.getMobile(), LoginLogTypeEnum.LOGIN_MOBILE, dataSourceCode); } - private void createLoginLog(Long userId, String username, Long organId, + private void createLoginLog(Long userId, String username, UserTypeEnum userTypeEnum, Long organId, LoginLogTypeEnum logTypeEnum, LoginResultEnum loginResult) { // 手动控制事务 transactionTemplate.executeWithoutResult(status -> { @@ -302,7 +321,7 @@ public class AdminAuthServiceImpl implements AdminAuthService { // 验证不通过 if (!response.isSuccess()) { // 创建登录失败日志(验证码不正确) - createLoginLog(null, reqVO.getUsername(), null, LoginLogTypeEnum.LOGIN_USERNAME, LoginResultEnum.CAPTCHA_CODE_ERROR); + createLoginLog(null, reqVO.getUsername(), null, null, LoginLogTypeEnum.LOGIN_USERNAME, LoginResultEnum.CAPTCHA_CODE_ERROR); throw ServiceExceptionUtil.exception(ErrorCodeConstants.AUTH_LOGIN_CAPTCHA_CODE_ERROR, response.getRepMsg()); } } @@ -318,7 +337,7 @@ public class AdminAuthServiceImpl implements AdminAuthService { */ private AuthLoginRespVO createTokenAfterLoginSuccess(AdminUserDO user, String username, LoginLogTypeEnum logType, String dataCode) { // 插入登陆日志 - createLoginLog(user.getId(), username, user.getOrganId(), logType, LoginResultEnum.SUCCESS); + createLoginLog(user.getId(), username, user.getUserType(), user.getOrganId(), logType, LoginResultEnum.SUCCESS); // 创建访问令牌 OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken(user, getUserType().getValue(), OAuth2ClientConstants.CLIENT_ID_DEFAULT, dataCode); // 构建返回结果 @@ -349,11 +368,7 @@ public class AdminAuthServiceImpl implements AdminAuthService { reqDTO.setTraceId(TracerUtils.getTraceId()); reqDTO.setUserId(userId); reqDTO.setUserType(userType); - if (ObjectUtil.equal(getUserType().getValue(), userType)) { - reqDTO.setUsername(getUsername(userId)); - } else { - reqDTO.setUsername(memberService.getMemberUserMobile(userId)); - } + reqDTO.setUsername(getUsername(userId)); // 设置登录时通过ip云服务查询到的地域信息 if (ipQueryService.serviceEnable()) { IPQueryDataRespDTO ipQueryDataRespDTO = ipQueryService.querySource(clientIP); diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/oauth2/OAuth2TokenServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/oauth2/OAuth2TokenServiceImpl.java index 6be765fb6..e04b5f74d 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/oauth2/OAuth2TokenServiceImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/oauth2/OAuth2TokenServiceImpl.java @@ -218,7 +218,7 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService { Long userId = user.getId(); OAuth2AccessTokenDO refreshToken = new OAuth2AccessTokenDO() .setUserId(userId) - .setUserType(userType) + .setUserType(user.getUserType().getValue()) .setDataCode(dataCode) .setOrganId(organId) .setNickname(user.getNickname()) @@ -228,8 +228,7 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService { if (organId != null) { OrganContextHolder.setOrganId(organId); } - boolean b = securityFrameworkService.hasAnyRoles(userId, "super_admin"); - refreshToken.setIsSupAdmin(b); + refreshToken.setIsSupAdmin(user.isSuperAdmin()); return refreshToken; } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/permission/MenuService.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/permission/MenuService.java index 66c918c3e..3bf907a1d 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/permission/MenuService.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/permission/MenuService.java @@ -86,4 +86,20 @@ public interface MenuService { List getMenuList(Collection ids); List getMenuList1(Collection ids); + + /** + * 查询管理端菜单列表 + * + * @param ids 菜单id列表 + * @return + */ + List getManageEndPointMenuList(Collection ids); + + /** + * 查询生产端菜单列表 + * + * @param ids 菜单id列表 + * @return + */ + List getCustomEndPointMenuList(Collection ids); } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/permission/MenuServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/permission/MenuServiceImpl.java index b2101237d..fa7088cfe 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/permission/MenuServiceImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/permission/MenuServiceImpl.java @@ -2,13 +2,17 @@ package com.cf.imes.module.system.service.permission; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; +import com.cf.imes.framework.common.exception.ServiceException; import com.cf.imes.framework.common.util.object.BeanUtils; +import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; import com.cf.imes.framework.organ.core.aop.OrganIgnore; +import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; import com.cf.imes.module.system.controller.admin.permission.vo.menu.MenuListReqVO; import com.cf.imes.module.system.controller.admin.permission.vo.menu.MenuSaveVO; import com.cf.imes.module.system.dal.dataobject.permission.MenuDO; import com.cf.imes.module.system.dal.mysql.permission.MenuMapper; import com.cf.imes.module.system.dal.redis.RedisKeyConstants; +import com.cf.imes.module.system.enums.permission.MenuSourceTypeEnum; import com.cf.imes.module.system.enums.permission.MenuTypeEnum; import com.cf.imes.module.system.service.organ.OrganService; import com.google.common.annotations.VisibleForTesting; @@ -64,6 +68,8 @@ public class MenuServiceImpl implements MenuService { validateParentMenu(createReqVO.getParentId(), null); // 校验菜单(自己) validateMenu(createReqVO.getParentId(), createReqVO.getName(), null); + // 校验管理端菜单增删改必须是晨丰组织下用户 + validateManageSourceTypeOperatePermission(createReqVO.getSourceType()); // 插入数据库 MenuDO menu = BeanUtils.toBean(createReqVO, MenuDO.class); @@ -91,6 +97,8 @@ public class MenuServiceImpl implements MenuService { validateParentMenu(updateReqVO.getParentId(), updateReqVO.getId()); // 校验菜单(自己) validateMenu(updateReqVO.getParentId(), updateReqVO.getName(), updateReqVO.getId()); + // 校验管理端菜单增删改必须是晨丰组织下用户 + validateManageSourceTypeOperatePermission(updateReqVO.getSourceType()); // 更新到数据库 MenuDO updateObj = BeanUtils.toBean(updateReqVO, MenuDO.class); @@ -119,6 +127,8 @@ public class MenuServiceImpl implements MenuService { if (menuDO == null) { throw exception(MENU_NOT_EXISTS); } + // 校验管理端菜单增删改必须是晨丰组织下用户 + validateManageSourceTypeOperatePermission(menuDO.getSourceType()); // 标记删除 menuMapper.deleteById(id); // 删除授予给角色的权限 @@ -128,6 +138,17 @@ public class MenuServiceImpl implements MenuService { flushCacheWhenOperateMenu(id, null, menuDO.getPermission()); } + /** + * 校验管理端菜单增删改必须是晨丰组织下用户 + * + * @param sourceType + */ + private void validateManageSourceTypeOperatePermission(Integer sourceType) { + if (!SecurityFrameworkUtils.isCfOrg() && sourceType.equals(MenuSourceTypeEnum.MANAGEMENT.getType())) { + throw new ServiceException(MANAGEMENT_MENU_OPERATION_PERMISSION_ERROR); + } + } + /** * 菜单增删改时清理缓存 * @@ -303,4 +324,21 @@ public class MenuServiceImpl implements MenuService { } } + @Override + @OrganIgnore + public List getManageEndPointMenuList(Collection ids) { + return menuMapper.selectList(new LambdaQueryWrapperX() + .inIfPresent(MenuDO::getId, ids) + .ne(MenuDO::getSourceType, MenuSourceTypeEnum.PRODUCTION.getType())); + } + + @Override + @OrganIgnore + public List getCustomEndPointMenuList(Collection ids) { + return menuMapper.selectList(new LambdaQueryWrapperX() + .inIfPresent(MenuDO::getId, ids) + .and(wr -> wr.or(wrapper -> wrapper + .isNull(MenuDO::getSourceType)) + .or(wrapper -> wrapper.ne(MenuDO::getSourceType, MenuSourceTypeEnum.MANAGEMENT.getType())))); + } } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/menu/MenuSourceTypeValid.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/menu/MenuSourceTypeValid.java new file mode 100644 index 000000000..c01f00716 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/menu/MenuSourceTypeValid.java @@ -0,0 +1,33 @@ +package com.cf.imes.module.system.validation.menu; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 菜单来源类型校验注解 + * + * @author Gqr + * @since 2024/10/21 11:25 + */ +@Target({ + ElementType.PARAMETER, + ElementType.FIELD, +}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Constraint( + validatedBy = {MenuSourceTypeValidator.class} +) +public @interface MenuSourceTypeValid { + String message() default "菜单类型不合法"; + + Class[] groups() default {}; + + Class[] payload() default {}; +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/menu/MenuSourceTypeValidator.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/menu/MenuSourceTypeValidator.java new file mode 100644 index 000000000..d9edda617 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/menu/MenuSourceTypeValidator.java @@ -0,0 +1,27 @@ +package com.cf.imes.module.system.validation.menu; + +import cn.hutool.core.util.ObjectUtil; +import com.cf.imes.module.system.enums.permission.MenuSourceTypeEnum; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; + +/** + * 菜单来源类型校验器 + * + * @author Gqr + * @since 2024/10/21 11:26 + */ +public class MenuSourceTypeValidator implements ConstraintValidator { + @Override + public boolean isValid(Integer value, ConstraintValidatorContext context) { + if (ObjectUtil.isNull(value)) { + return true; + } + for (MenuSourceTypeEnum typeEnum : MenuSourceTypeEnum.values()) { + if (ObjectUtil.equal(typeEnum.getType(), value)) { + return true; + } + } + return false; + } +} diff --git a/cf-module-system/cf-module-system-biz/src/main/resources/application-dev.yaml b/cf-module-system/cf-module-system-biz/src/main/resources/application-dev.yaml index f34f9ecbd..0b3c60744 100644 --- a/cf-module-system/cf-module-system-biz/src/main/resources/application-dev.yaml +++ b/cf-module-system/cf-module-system-biz/src/main/resources/application-dev.yaml @@ -181,6 +181,7 @@ chenfeng: - /admin-api/system/machine-template/* - /admin-api/system/data-source/* - /admin-api/system/auth/login + - /admin-api/system/auth/manage/login - /admin-api/system/auth/logout - /admin-api/system/auth/sms-code - /admin-api/system/user/reset-password diff --git a/cf-module-system/cf-module-system-biz/src/main/resources/application-local.yaml b/cf-module-system/cf-module-system-biz/src/main/resources/application-local.yaml index f19e009c8..6c76178f9 100644 --- a/cf-module-system/cf-module-system-biz/src/main/resources/application-local.yaml +++ b/cf-module-system/cf-module-system-biz/src/main/resources/application-local.yaml @@ -58,10 +58,6 @@ spring: name: imes_base url: jdbc:mysql://192.168.1.205:3307/${spring.datasource.dynamic.datasource.master.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 driver-class-name: com.mysql.cj.jdbc.Driver -# url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例 -# url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.master.name} # PostgreSQL 连接的示例 -# url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 -# url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.master.name} # SQLServer 连接的示例 username: root password: root # username: sa @@ -204,6 +200,7 @@ chenfeng: - /admin-api/system/machine-template/* - /admin-api/system/data-source/* - /admin-api/system/auth/login + - /admin-api/system/auth/manage/login - /admin-api/system/auth/logout - /admin-api/system/auth/sms-code - /admin-api/system/user/reset-password