yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java
@@ -16,6 +16,7 @@
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*;
import cn.iocoder.yudao.module.system.convert.auth.AuthConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum;
@@ -26,6 +27,8 @@
import cn.iocoder.yudao.module.system.service.logger.LoginLogService;
import cn.iocoder.yudao.module.system.service.member.MemberService;
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService;
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
import cn.iocoder.yudao.module.system.service.permission.RoleService;
import cn.iocoder.yudao.module.system.service.social.SocialUserService;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import com.anji.captcha.model.common.ResponseModel;
@@ -43,6 +46,7 @@
import org.springframework.transaction.annotation.Transactional;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -62,6 +66,14 @@
     * 企业微信社交类型,对应 {@link cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum#WECHAT_ENTERPRISE}
     */
    private static final Integer WECHAT_ENTERPRISE_TYPE = 30;
    /**
     * 企业微信扫码自动注册的账号,默认绑定的角色编码。
     *
     * 需要在「系统管理 → 角色管理」里建好该编码的角色并勾选菜单,否则新账号登录后没有任何菜单。
     * 编码而非角色编号:角色编号在本地/测试/生产各库不一致,写死会在换库后静默失效。
     */
    private static final String WXCP_DEFAULT_ROLE_CODE = "wxcp_user";
    @Resource
    private AdminUserService userService;
@@ -85,6 +97,10 @@
    private PasswordEncoder passwordEncoder;
    @Resource
    private ApplicationEventPublisher eventPublisher;
    @Resource
    private RoleService roleService;
    @Resource
    private PermissionService permissionService;
    /**
     * 验证码的开关,默认为 true
@@ -267,9 +283,35 @@
        user.setStatus(CommonStatusEnum.ENABLE.getStatus());
        userMapper.insert(user);
        // 5. 绑定默认角色
        //    不绑的话账号能登录,但 get-permission-info 返回空菜单,进去一片空白;
        //    这种"能进但什么都看不到"的状态不会报错,很难定位,所以注册时就绑上
        bindDefaultRole(user);
        return user;
    }
    /**
     * 给自动注册的账号绑定默认角色
     *
     * 角色不存在时只打警告、不抛异常:一个配置遗漏不应该让扫码登录整条链路不可用,
     * 而且警告日志里已经写明了去哪儿补。
     *
     * @param user 自动注册出来的用户
     */
    private void bindDefaultRole(AdminUserDO user) {
        RoleDO role = roleService.getRoleByCode(WXCP_DEFAULT_ROLE_CODE);
        if (role == null) {
            log.warn("[bindDefaultRole][角色编码({}) 不存在,用户({}) 将没有任何菜单权限;" +
                            "请在「系统管理 → 角色管理」新建编码为 {} 的角色并分配菜单]",
                    WXCP_DEFAULT_ROLE_CODE, user.getUsername(), WXCP_DEFAULT_ROLE_CODE);
            return;
        }
        permissionService.assignUserRole(user.getId(), Set.of(role.getId()));
        log.info("[bindDefaultRole][用户({}) 已绑定默认角色({}/{})]",
                user.getUsername(), role.getCode(), role.getName());
    }
    @VisibleForTesting
    void validateCaptcha(AuthLoginReqVO reqVO) {
        ResponseModel response = doValidateCaptcha(reqVO);