@Override
    @Transactional
    public boolean checkForPreApproval(Long userId, Integer userType, String clientId, Collection<String> requestedScopes) {
        // 第一步，基于 Client 的自动授权计算，如果 scopes 都在自动授权中，则返回 true 通过
        OAuth2ClientDO clientDO = oauth2ClientService.validOAuthClientFromCache(clientId);
        Assert.notNull(clientDO, "客户端不能为空"); // 防御性编程
        if (CollUtil.containsAll(clientDO.getAutoApproveScopes(), requestedScopes)) {
            // gh-877 - if all scopes are auto approved, approvals still need to be added to the approval store.
            LocalDateTime expireTime = LocalDateTime.now().plusSeconds(TIMEOUT);
            for (String scope : requestedScopes) {
                saveApprove(userId, userType, clientId, scope, true, expireTime);
            }
            return true;
        }

        // 第二步，算上用户已经批准的授权。如果 scopes 都包含，则返回 true
        List<OAuth2ApproveDO> approveDOs = getApproveList(userId, userType, clientId);
        Set<String> scopes = convertSet(approveDOs, OAuth2ApproveDO::getScope,
                OAuth2ApproveDO::getApproved); // 只保留未过期的 + 同意的
        return CollUtil.containsAll(scopes, requestedScopes);
    }
@Test
    public void checkForPreApproval_approve() {
        // 准备参数
        Long userId = randomLongId();
        Integer userType = randomEle(UserTypeEnum.values()).getValue();
        String clientId = randomString();
        List<String> requestedScopes = Lists.newArrayList("read");
        // mock 方法
        when(oauth2ClientService.validOAuthClientFromCache(eq(clientId)))
                .thenReturn(randomPojo(OAuth2ClientDO.class).setAutoApproveScopes(null));
        // mock 数据
        OAuth2ApproveDO approve = randomPojo(OAuth2ApproveDO.class).setUserId(userId)
                .setUserType(userType).setClientId(clientId).setScope("read")
                .setExpiresTime(LocalDateTimeUtil.offset(LocalDateTime.now(), 1L, ChronoUnit.DAYS)).setApproved(true); // 同意
        oauth2ApproveMapper.insert(approve);

        // 调用
        boolean success = oauth2ApproveService.checkForPreApproval(userId, userType,
                clientId, requestedScopes);
        // 断言
        assertTrue(success);
    }