Browse Source

目录功能

tangxiangan 10 months ago
parent
commit
2e59bf5e51
54 changed files with 1758 additions and 100 deletions
  1. 5 1
      pdf-tech-common/src/main/java/enums/ValidStatusEnum.java
  2. 23 0
      pdf-tech-core/pom.xml
  3. 7 1
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/PdfTechCoreApplication.java
  4. 13 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/constant/SSOConstant.java
  5. 41 1
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/controller/DirectoryController.java
  6. 1 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/controller/VppLicenseCodeController.java
  7. 36 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/controller/VppMemberController.java
  8. 158 6
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/controller/VppRTeamMemberRoleController.java
  9. 42 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/converter/SSOMemberStatusConverter.java
  10. 3 2
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/enums/MemberStatusEnum.java
  11. 40 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/enums/SSOMemberStatusEnum.java
  12. 18 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/enums/ScheduleSettingTypeEnum.java
  13. 23 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/enums/ScpoeEnum.java
  14. 18 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/enums/SyncStatusEnum.java
  15. 17 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/enums/SyncUserEnum.java
  16. 1 1
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/mapper/ext/ExtVppRTeamMemberRoleMapper.java
  17. 37 1
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/model/Directory.java
  18. 150 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/model/DirectoryExample.java
  19. 19 1
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/model/VppMember.java
  20. 91 16
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/model/VppMemberExample.java
  21. 9 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/pojo/MSGroup.java
  22. 29 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/pojo/dto/AddSyncDTO.java
  23. 2 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/pojo/dto/CreateTeamDTO.java
  24. 1 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/pojo/dto/DirectoryUpdateDTO.java
  25. 19 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/pojo/dto/ScheduleSettingDTO.java
  26. 33 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/pojo/vo/SSODeletedMemberVO.java
  27. 27 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/pojo/vo/SSOMemberLicenseVO.java
  28. 42 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/pojo/vo/SSOMemberVO.java
  29. 5 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/pojo/vo/VppTeamMemberVO.java
  30. 6 2
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/DirectoryService.java
  31. 4 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/DirectorySyncService.java
  32. 3 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/ProductService.java
  33. 13 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/ScheduleSettingService.java
  34. 29 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/SyncService.java
  35. 7 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/VppLicenseCodeService.java
  36. 7 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/VppMemberService.java
  37. 25 2
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/VppRTeamMemberRoleService.java
  38. 46 2
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/impl/DirectoryServiceImpl.java
  39. 10 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/impl/DirectorySyncServiceImpl.java
  40. 11 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/impl/DomainServiceImpl.java
  41. 8 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/impl/ProductServiceImpl.java
  42. 73 1
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/impl/ScheduleSettingServiceImpl.java
  43. 281 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/impl/SyncServiceImpl.java
  44. 2 1
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/impl/VppDeviceServiceImpl.java
  45. 37 19
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/impl/VppLicenseCodeServiceImpl.java
  46. 9 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/impl/VppMemberServiceImpl.java
  47. 47 4
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/impl/VppRTeamMemberRoleServiceImpl.java
  48. 2 2
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/impl/VppTeamServiceImpl.java
  49. 109 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/utils/QuartzUtils.java
  50. 27 0
      pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/utils/SyncJob.java
  51. 2 2
      pdf-tech-core/src/main/resources/generatorConfig.xml
  52. 37 5
      pdf-tech-core/src/main/resources/sqlmap/DirectoryMapper.xml
  53. 41 26
      pdf-tech-core/src/main/resources/sqlmap/VppMemberMapper.xml
  54. 12 4
      pdf-tech-core/src/main/resources/sqlmap/ext/ExtVppRTeamMemberRoleMapper.xml

+ 5 - 1
pdf-tech-common/src/main/java/enums/ValidStatusEnum.java

@@ -15,7 +15,11 @@ public enum ValidStatusEnum {
     /**
      * 有效
      */
-    VALID("1");
+    VALID("1"),
+    /**
+     * 吊销的用户
+     */
+    REVOKED("3");
 
     private final String value;
 

+ 23 - 0
pdf-tech-core/pom.xml

@@ -171,6 +171,29 @@
             <artifactId>dnsjava</artifactId>
             <version>2.1.8</version>
         </dependency>
+
+        <dependency>
+            <groupId>com.microsoft.kiota</groupId>
+            <artifactId>microsoft-kiota-serialization-json</artifactId>
+            <version>1.0.3</version>
+        </dependency>
+        <dependency>
+            <!-- Include the sdk as a dependency -->
+            <groupId>com.microsoft.graph</groupId>
+            <artifactId>microsoft-graph</artifactId>
+            <version>6.5.0</version>
+        </dependency>
+        <dependency>
+            <!-- This dependency is only needed if you are using a TokenCredential object for authentication -->
+            <groupId>com.azure</groupId>
+            <artifactId>azure-identity</artifactId>
+            <version>1.11.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.quartz-scheduler</groupId>
+            <artifactId>quartz</artifactId>
+            <version>2.3.2</version>
+        </dependency>
     </dependencies>
 
     <dependencyManagement>

+ 7 - 1
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/PdfTechCoreApplication.java

@@ -1,5 +1,10 @@
 package cn.kdan.pdf.tech.core;
 
+import cn.kdan.pdf.tech.core.enums.ScheduleSettingTypeEnum;
+import cn.kdan.pdf.tech.core.model.ScheduleSetting;
+import cn.kdan.pdf.tech.core.service.ScheduleSettingService;
+import cn.kdan.pdf.tech.core.utils.QuartzUtils;
+import cn.kdan.pdf.tech.core.utils.SyncJob;
 import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -11,7 +16,9 @@ import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfi
 import org.springframework.context.annotation.Bean;
 import org.springframework.scheduling.annotation.EnableScheduling;
 
+import javax.annotation.Resource;
 import java.text.SimpleDateFormat;
+import java.util.List;
 
 /**
  * @author tangxiangan
@@ -30,7 +37,6 @@ public class PdfTechCoreApplication {
         objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
         return objectMapper;
     }
-
     public static void main(String[] args) {
         SpringApplication.run(PdfTechCoreApplication.class, args);
     }

+ 13 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/constant/SSOConstant.java

@@ -0,0 +1,13 @@
+package cn.kdan.pdf.tech.core.constant;
+
+/**
+ * @author tangxiangan
+ */
+public interface SSOConstant {
+    String DIRECTORY_NOT_EXIST = "Directory does not exist";
+    String DIRECTORY_EXIST = "Directory name already exists";
+    String GRAPH_SCOPE = "https://graph.microsoft.com/.default";
+    String EXCEPTION_MSG_MEMBER_NOT_EXIST = "用户未同步";
+    String EXCEPTION_MSG_MEMBER_REVOKED = "用户已吊销";
+    String EXCEPTION_MSG_MEMBER_HAS_ASSIGNED = "用户未授权";
+}

+ 41 - 1
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/controller/DirectoryController.java

@@ -1,10 +1,15 @@
 package cn.kdan.pdf.tech.core.controller;
 
 import cn.kdan.pdf.tech.core.model.Directory;
+import cn.kdan.pdf.tech.core.pojo.MSGroup;
+import cn.kdan.pdf.tech.core.pojo.dto.AddSyncDTO;
 import cn.kdan.pdf.tech.core.pojo.dto.DirectoryCreateDTO;
 import cn.kdan.pdf.tech.core.pojo.dto.DirectoryUpdateDTO;
+import cn.kdan.pdf.tech.core.pojo.dto.ScheduleSettingDTO;
 import cn.kdan.pdf.tech.core.pojo.vo.DirectoryVO;
 import cn.kdan.pdf.tech.core.service.DirectoryService;
+import cn.kdan.pdf.tech.core.service.ScheduleSettingService;
+import cn.kdan.pdf.tech.core.service.SyncService;
 import constant.CommonConstant;
 import org.springframework.web.bind.annotation.*;
 import pojo.ResultMap;
@@ -20,6 +25,10 @@ public class DirectoryController {
 
     @Resource
     private DirectoryService directoryService;
+    @Resource
+    private SyncService syncService;
+    @Resource
+    private ScheduleSettingService scheduleSettingService;
 
     /**
      * 获取目录列表
@@ -63,8 +72,39 @@ public class DirectoryController {
      * @return Directory
      */
     @PostMapping("/update")
-    public ResultMap<Directory> create(@RequestBody @Valid DirectoryUpdateDTO updateDTO) {
+    public ResultMap<String> create(@RequestBody @Valid DirectoryUpdateDTO updateDTO) {
         directoryService.update(updateDTO);
         return new ResultMap<>(CommonConstant.SUCCESS, CommonConstant.RESULT_SUCCESS);
     }
+
+    /**
+     * 添加同步设置
+     *
+     * @param addSyncDTO 同步设置
+     * @return String
+     */
+    @PostMapping("/addSyncSettings")
+    public ResultMap<String> addSyncSettings(@RequestBody @Valid AddSyncDTO addSyncDTO) {
+        syncService.addSyncSettings(addSyncDTO);
+        return new ResultMap<>(CommonConstant.SUCCESS, CommonConstant.RESULT_SUCCESS);
+    }
+
+    /**
+     * 获取组列表
+     * @param clientId clientId
+     * @param tenantId tenantId
+     * @param clientSecret clientSecret
+     * @return List
+     */
+    @GetMapping("/getGroupList")
+    public ResultMap<List<MSGroup>> getGroupList(@RequestParam String clientId, @RequestParam String tenantId, @RequestParam String clientSecret) {
+        List<MSGroup> directoryList = syncService.getGroupList(clientId, tenantId, clientSecret);
+        return new ResultMap<>(CommonConstant.SUCCESS, CommonConstant.RESULT_SUCCESS, directoryList);
+    }
+
+    @PostMapping("/syncSetting")
+    public ResultMap<String> syncSetting(@RequestBody @Valid ScheduleSettingDTO scheduleSettingDTO) {
+        scheduleSettingService.syncSetting(scheduleSettingDTO);
+        return new ResultMap<>(CommonConstant.SUCCESS, CommonConstant.RESULT_SUCCESS);
+    }
 }

+ 1 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/controller/VppLicenseCodeController.java

@@ -188,4 +188,5 @@ public class VppLicenseCodeController {
         vppLicenseCodeService.disable(licenseCodeId);
         return new ResultMap<>(CommonConstant.SUCCESS, CommonConstant.RESULT_SUCCESS, CommonConstant.RESULT_SUCCESS);
     }
+
 }

+ 36 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/controller/VppMemberController.java

@@ -2,19 +2,32 @@ package cn.kdan.pdf.tech.core.controller;
 
 import cn.hutool.core.bean.BeanUtil;
 import cn.kdan.pdf.tech.core.constant.AuthConstant;
+import cn.kdan.pdf.tech.core.constant.SSOConstant;
+import cn.kdan.pdf.tech.core.constant.VppLicenseCodeConstant;
 import cn.kdan.pdf.tech.core.constant.VppMemberConstant;
+import cn.kdan.pdf.tech.core.model.LicenseCodes;
 import cn.kdan.pdf.tech.core.model.VppMember;
 import cn.kdan.pdf.tech.core.params.VppMemberRegisterParam;
 import cn.kdan.pdf.tech.core.params.VppMemberResetPwdParam;
 import cn.kdan.pdf.tech.core.params.VppMemberUpdatePwdParam;
+import cn.kdan.pdf.tech.core.pojo.vo.SSOMemberLicenseVO;
 import cn.kdan.pdf.tech.core.pojo.vo.VppMemberVO;
+import cn.kdan.pdf.tech.core.service.VppLicenseCodeService;
 import cn.kdan.pdf.tech.core.service.VppMemberService;
+import com.azure.core.implementation.util.ObjectsUtil;
 import constant.CommonConstant;
+import enums.ValidStatusEnum;
+import exception.BackendRuntimeException;
+import org.springframework.beans.BeanUtils;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
 import org.springframework.web.bind.annotation.*;
 import pojo.ResultMap;
 
 import javax.annotation.Resource;
 import javax.validation.Valid;
+import java.util.List;
+import java.util.Objects;
 
 /**
  * @author tangxiangan
@@ -25,6 +38,8 @@ public class VppMemberController {
 
     @Resource
     private VppMemberService vppMemberService;
+    @Resource
+    private VppLicenseCodeService licenseCodeService;
 
     /**
      * 用户注册
@@ -94,4 +109,25 @@ public class VppMemberController {
         vppMemberVO.setDigestPassword(null);
         return new ResultMap<>(CommonConstant.SUCCESS, CommonConstant.RESULT_SUCCESS, vppMemberVO);
     }
+
+    @GetMapping("/checkSSOMember")
+    public ResultMap<SSOMemberLicenseVO> checkSSOMember(@RequestParam("email") String email,@RequestParam("productCode") String productCode) {
+        VppMember member = vppMemberService.getByAccountSSO(email);
+        if (ObjectUtils.isEmpty(member)) {
+            throw new BackendRuntimeException(SSOConstant.EXCEPTION_MSG_MEMBER_NOT_EXIST);
+        }
+        if(member.getValidFlag().equals(ValidStatusEnum.REVOKED.value())){
+            throw new BackendRuntimeException(SSOConstant.EXCEPTION_MSG_MEMBER_REVOKED);
+        }
+        LicenseCodes codes = licenseCodeService.getByMemberId(member.getId(),productCode);
+        if(!ObjectUtils.isEmpty(codes)){
+            throw new BackendRuntimeException(SSOConstant.EXCEPTION_MSG_MEMBER_HAS_ASSIGNED);
+        }
+        SSOMemberLicenseVO ssoMemberLicenseVO = new SSOMemberLicenseVO();
+        BeanUtils.copyProperties(member,ssoMemberLicenseVO);
+        BeanUtils.copyProperties(codes,ssoMemberLicenseVO);
+
+        return new ResultMap<>(CommonConstant.SUCCESS, VppLicenseCodeConstant.SUCCESS_MSG_ASSIGN, ssoMemberLicenseVO);
+    }
+
 }

+ 158 - 6
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/controller/VppRTeamMemberRoleController.java

@@ -2,18 +2,21 @@ package cn.kdan.pdf.tech.core.controller;
 
 import cn.kdan.pdf.tech.core.aspect.PreCheckRole;
 import cn.kdan.pdf.tech.core.enums.RoleEnum;
+import cn.kdan.pdf.tech.core.enums.SyncUserEnum;
 import cn.kdan.pdf.tech.core.model.VppCompany;
-import cn.kdan.pdf.tech.core.pojo.vo.VppDeviceVO;
-import cn.kdan.pdf.tech.core.pojo.vo.VppTeamAdminVO;
-import cn.kdan.pdf.tech.core.pojo.vo.VppTeamMemberVO;
-import cn.kdan.pdf.tech.core.pojo.vo.VppTeamMenberVO;
+import cn.kdan.pdf.tech.core.pojo.vo.*;
+import cn.kdan.pdf.tech.core.service.DirectoryService;
 import cn.kdan.pdf.tech.core.service.VppCompanyService;
 import cn.kdan.pdf.tech.core.service.VppRTeamMemberRoleService;
+import cn.kdan.pdf.tech.core.service.VppTeamService;
 import com.alibaba.excel.EasyExcel;
 import com.alibaba.excel.util.MapUtils;
+import com.alibaba.excel.util.StringUtils;
 import com.alibaba.fastjson.JSON;
 import com.github.pagehelper.PageInfo;
 import constant.CommonConstant;
+import enums.ValidStatusEnum;
+import org.bouncycastle.util.Strings;
 import org.springframework.web.bind.annotation.*;
 import pojo.ResultMap;
 import utils.CommonUtils;
@@ -22,6 +25,7 @@ import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.net.URLEncoder;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
@@ -36,6 +40,8 @@ public class VppRTeamMemberRoleController {
     private VppRTeamMemberRoleService vppRTeamMemberRoleService;
     @Resource
     private VppCompanyService vppCompanyService;
+    @Resource
+    private DirectoryService directoryService;
 
     /**
      * 超管分页获取所在公司团队的管理员信息
@@ -65,7 +71,20 @@ public class VppRTeamMemberRoleController {
                                                               @RequestParam(required = false) String status,
                                                               @RequestParam(required = false) String productCode,
                                                               @RequestParam(required = false) String queryString) {
-        return new ResultMap<>(CommonConstant.SUCCESS, CommonConstant.RESULT_SUCCESS, vppRTeamMemberRoleService.pageForMember(page, pageSize, teamId, status, productCode,queryString));
+        return new ResultMap<>(CommonConstant.SUCCESS, CommonConstant.RESULT_SUCCESS, vppRTeamMemberRoleService.pageForMember(page, pageSize, teamId, status, productCode, queryString, null));
+    }
+
+    @GetMapping("/pageForSSOMember")
+    public ResultMap<PageInfo<VppTeamMemberVO>> pageForSSOMember(@RequestParam(required = false, defaultValue = "1") Integer page,
+                                                                 @RequestParam(required = false, defaultValue = "10") Integer pageSize,
+                                                                 @RequestParam(required = false) String directoryId,
+                                                                 @RequestParam(required = false) String status,
+                                                                 @RequestParam(required = false) String queryString) {
+        if (StringUtils.isEmpty(directoryId)){
+            String teamId = directoryService.getById(directoryId).getTeamId();
+            return new ResultMap<>(CommonConstant.SUCCESS, CommonConstant.RESULT_SUCCESS, vppRTeamMemberRoleService.pageForMember(page, pageSize, teamId, status, null, queryString, SyncUserEnum.SSO.value()));
+        }
+        return new ResultMap<>(CommonConstant.SUCCESS, CommonConstant.RESULT_SUCCESS, vppRTeamMemberRoleService.pageForMember(page, pageSize, null, status, null, queryString, SyncUserEnum.SSO.value()));
     }
 
 
@@ -89,7 +108,7 @@ public class VppRTeamMemberRoleController {
                     .sheet("模板")
                     .doWrite(() -> {
                         // 分页查询数据
-                        return vppRTeamMemberRoleService.listForMember( teamId, status, productCode, queryString);
+                        return vppRTeamMemberRoleService.listForMember(teamId, status, productCode, queryString, null);
                     });
         } catch (Exception e) {
             // 重置response
@@ -103,6 +122,96 @@ public class VppRTeamMemberRoleController {
         }
     }
 
+    @GetMapping("/downloadSSOMember")
+    public void downloadSSOMember(HttpServletResponse response,
+                                  @RequestParam(required = false) String directoryId,
+                                  @RequestParam(required = false) String status,
+                                  @RequestParam(required = false) String queryString) throws IOException {
+        // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
+        try {
+            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+            response.setCharacterEncoding("utf-8");
+            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
+            VppCompany company = vppCompanyService.getUserCompany();
+            String fileName = URLEncoder.encode(company.getName()+ " " + CommonUtils.getDateTime("yyyyMMdd") +" Member Directory", "UTF-8").replaceAll("\\+", "%20");
+            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
+            // 这里需要设置不关闭流
+            EasyExcel.write(response.getOutputStream(), SSOMemberVO.class)
+                    .autoCloseStream(Boolean.FALSE)
+                    .sheet("模板")
+                    .doWrite(() -> {
+                        List<VppTeamMemberVO> list ;
+                        if (StringUtils.isEmpty(directoryId)){
+                            String teamId = directoryService.getById(directoryId).getTeamId();
+                            list = vppRTeamMemberRoleService.listForMember(teamId, status, null, queryString, SyncUserEnum.SSO.value());
+
+                        }else {
+                            list = vppRTeamMemberRoleService.listForMember(null, status, null, queryString, SyncUserEnum.SSO.value());
+                        }
+                        List<SSOMemberVO> ssoMemberVOList = new ArrayList<>();
+                        list.forEach(item -> {
+                            if (!StringUtils.isEmpty(item.getEmail())){
+                                SSOMemberVO ssoMemberVO = new SSOMemberVO();
+                                ssoMemberVO.setEmail(item.getEmail());
+                                ssoMemberVO.setFullName(item.getFullName());
+                                ssoMemberVO.setValidFlag(item.getValidFlag());
+                                ssoMemberVO.setUpdatedAt(item.getUpdatedAt());
+                                ssoMemberVOList.add(ssoMemberVO);
+                            }
+                        });
+                        return ssoMemberVOList;
+                    });
+        } catch (Exception e) {
+            // 重置response
+            response.reset();
+            response.setContentType("application/json");
+            response.setCharacterEncoding("utf-8");
+            Map<String, String> map = MapUtils.newHashMap();
+            map.put("status", "failure");
+            map.put("message", "下载文件失败" + e.getMessage());
+            response.getWriter().println(JSON.toJSONString(map));
+        }
+    }
+
+    @GetMapping("/downloadUnValidSSOMember")
+    public void downloadUnVaildSSOMember(HttpServletResponse response,
+                                  @RequestParam(required = false) String queryString) throws IOException {
+        // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
+        try {
+            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+            response.setCharacterEncoding("utf-8");
+            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
+            VppCompany company = vppCompanyService.getUserCompany();
+            String fileName = URLEncoder.encode(company.getName()+ " " + CommonUtils.getDateTime("yyyyMMdd") +" Member Deleted", "UTF-8").replaceAll("\\+", "%20");
+            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
+            // 这里需要设置不关闭流
+            EasyExcel.write(response.getOutputStream(), SSODeletedMemberVO.class)
+                    .autoCloseStream(Boolean.FALSE)
+                    .sheet("模板")
+                    .doWrite(() -> {
+                        List<VppTeamMemberVO> list = vppRTeamMemberRoleService.listForMember(null, ValidStatusEnum.INVALID.value(), null, queryString, SyncUserEnum.SSO.value());
+                        List<SSODeletedMemberVO> ssoMemberVOList = new ArrayList<>();
+                        list.forEach(item -> {
+                            if (!StringUtils.isEmpty(item.getEmail())){
+                                SSODeletedMemberVO vo = new SSODeletedMemberVO();
+                                vo.setEmail(item.getEmail());
+                                vo.setFullName(item.getFullName());
+                                ssoMemberVOList.add(vo);
+                            }
+                        });
+                        return ssoMemberVOList;
+                    });
+        } catch (Exception e) {
+            // 重置response
+            response.reset();
+            response.setContentType("application/json");
+            response.setCharacterEncoding("utf-8");
+            Map<String, String> map = MapUtils.newHashMap();
+            map.put("status", "failure");
+            map.put("message", "下载文件失败" + e.getMessage());
+            response.getWriter().println(JSON.toJSONString(map));
+        }
+    }
 
     /**
      * 获取团队下所有用户,根据邮箱去重
@@ -142,4 +251,47 @@ public class VppRTeamMemberRoleController {
         return new ResultMap<>(CommonConstant.SUCCESS, CommonConstant.RESULT_SUCCESS, Boolean.TRUE);
     }
 
+    /**
+     * 删除ms用户
+     * @param memberId 用户id
+     * @return Boolean
+     */
+    @PostMapping("/removeSSOMember")
+    public ResultMap<Boolean> removeSSOMember(@RequestParam String memberId){
+        vppRTeamMemberRoleService.removeSSOMembers(memberId);
+        return new ResultMap<>(CommonConstant.SUCCESS, CommonConstant.RESULT_SUCCESS, Boolean.TRUE);
+    }
+
+    /**
+     * 还原ms用户
+     * @param memberId 用户id
+     * @return Boolean
+     */
+    @PostMapping("/reductionSSOMember")
+    public ResultMap<Boolean> reductionSSOMember(@RequestParam String memberId){
+        vppRTeamMemberRoleService.reductionSSOMember(memberId);
+        return new ResultMap<>(CommonConstant.SUCCESS, CommonConstant.RESULT_SUCCESS, Boolean.TRUE);
+    }
+
+    /**
+     * 吊销ms用户
+     * @param memberId 用户id
+     * @return Boolean
+     */
+    @PostMapping("/revokeSSOMember")
+    public ResultMap<Boolean> revokeSSOMember(@RequestParam String memberId){
+        vppRTeamMemberRoleService.revokeSSOMember(memberId);
+        return new ResultMap<>(CommonConstant.SUCCESS, CommonConstant.RESULT_SUCCESS, Boolean.TRUE);
+    }
+
+    /**
+     * 取消吊销用户
+     * @param memberId 用户id
+     * @return Boolean
+     */
+    @PostMapping("/accessSSOMember")
+    public ResultMap<Boolean>  accessSSOMember(@RequestParam String memberId){
+        vppRTeamMemberRoleService.accessSSOMember(memberId);
+        return new ResultMap<>(CommonConstant.SUCCESS, CommonConstant.RESULT_SUCCESS, Boolean.TRUE);
+    }
 }

+ 42 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/converter/SSOMemberStatusConverter.java

@@ -0,0 +1,42 @@
+package cn.kdan.pdf.tech.core.converter;
+
+import cn.kdan.pdf.tech.core.enums.SSOMemberStatusEnum;
+import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.converters.ReadConverterContext;
+import com.alibaba.excel.converters.WriteConverterContext;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+import com.alibaba.excel.metadata.data.WriteCellData;
+
+public class SSOMemberStatusConverter implements Converter<String> {
+    @Override
+    public Class<?> supportJavaTypeKey() {
+        return String.class;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return CellDataTypeEnum.STRING;
+    }
+
+    /**
+     * 这里读的时候会调用
+     *
+     * @param context
+     * @return
+     */
+    @Override
+    public String convertToJavaData(ReadConverterContext<?> context) {
+        return context.getReadCellData().getStringValue();
+    }
+
+    /**
+     * 这里是写的时候会调用 不用管
+     *
+     * @return
+     */
+    @Override
+    public WriteCellData<?> convertToExcelData(WriteConverterContext<String> context) {
+        return new WriteCellData<>(SSOMemberStatusEnum.getEnumByCode(context.getValue()).value());
+    }
+
+}

+ 3 - 2
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/enums/MemberStatusEnum.java

@@ -1,7 +1,7 @@
 package cn.kdan.pdf.tech.core.enums;
 
 /**
- * 序列码枚举类
+ * 用户状态枚举类
  *
  * @author tangxiangan
  */
@@ -9,7 +9,8 @@ public enum MemberStatusEnum {
 
     DELETED("0","Deleted"),
     INVITED("2","Invited"),
-    JOINED("1","Joined");
+    JOINED("1","Joined"),
+    REVOKED("3","Revoked");
 
     private String code;
 

+ 40 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/enums/SSOMemberStatusEnum.java

@@ -0,0 +1,40 @@
+package cn.kdan.pdf.tech.core.enums;
+
+/**
+ * 用户状态枚举类
+ *
+ * @author tangxiangan
+ */
+public enum SSOMemberStatusEnum {
+
+    DELETED("0","Deleted"),
+    VALID_ACCESS("1","Valid Access"),
+    REVOKED("2","Revoked");
+
+    private String code;
+
+    private String value;
+
+    SSOMemberStatusEnum(String code, String value) {
+        this.code = code;
+        this.value = value;
+    }
+
+
+    public static SSOMemberStatusEnum getEnumByCode(String code) {
+        for (SSOMemberStatusEnum type : SSOMemberStatusEnum.values()) {
+            if (type.code().equals(code)) {
+                return type;
+            }
+        }
+        return null;
+    }
+
+    public String code() {
+        return code;
+    }
+
+    public String value() {
+        return value;
+    }
+}

+ 18 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/enums/ScheduleSettingTypeEnum.java

@@ -0,0 +1,18 @@
+package cn.kdan.pdf.tech.core.enums;
+
+public enum ScheduleSettingTypeEnum {
+
+    SYNC_NOW("0"),
+    PER_HOUR("1"),
+    SPECIFIED_TIME_EVERY_DAY("2");
+
+    private final String value;
+
+    ScheduleSettingTypeEnum(String value) {
+        this.value = value;
+    }
+
+    public String value() {
+        return value;
+    }
+}

+ 23 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/enums/ScpoeEnum.java

@@ -0,0 +1,23 @@
+package cn.kdan.pdf.tech.core.enums;
+
+public enum ScpoeEnum {
+
+    /**
+     * 全部用户团队
+     */
+    ALL("1"),
+    /**
+     * 指定用户团队
+     */
+    SPECIFY("2");
+
+    private final String value;
+
+    ScpoeEnum(String value) {
+        this.value = value;
+    }
+
+    public String value() {
+        return value;
+    }
+}

+ 18 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/enums/SyncStatusEnum.java

@@ -0,0 +1,18 @@
+package cn.kdan.pdf.tech.core.enums;
+
+public enum SyncStatusEnum {
+
+    SYNC_ING("0"),
+    SYNC_FINISHED("1"),
+    SYNC_FAILED("2");
+
+    private final String value;
+
+    SyncStatusEnum(String value) {
+        this.value = value;
+    }
+
+    public String value() {
+        return value;
+    }
+}

+ 17 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/enums/SyncUserEnum.java

@@ -0,0 +1,17 @@
+package cn.kdan.pdf.tech.core.enums;
+
+public enum SyncUserEnum {
+
+    NO("0"),
+    SSO("1");
+
+    private final String value;
+
+    SyncUserEnum(String value) {
+        this.value = value;
+    }
+
+    public String value() {
+        return value;
+    }
+}

+ 1 - 1
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/mapper/ext/ExtVppRTeamMemberRoleMapper.java

@@ -43,7 +43,7 @@ public interface ExtVppRTeamMemberRoleMapper extends VppRTeamMemberRoleMapper {
      * @param status
      * @return
      */
-    List<VppTeamMemberVO> listForMember(@Param("teamIds") List<String> teamIds, @Param("email") String email, @Param("queryString") String queryString, @Param("status") String status, @Param("productCode") String productCode);
+    List<VppTeamMemberVO> listForMember(@Param("teamIds") List<String> teamIds, @Param("email") String email, @Param("queryString") String queryString, @Param("status") String status, @Param("productCode") String productCode,@Param("isSso") String isSso);
 
 
     /**

+ 37 - 1
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/model/Directory.java

@@ -26,6 +26,10 @@ public class Directory implements Serializable {
 
     private String companyId;
 
+    private String teamId;
+
+    private String msGroupIds;
+
     private static final long serialVersionUID = 1L;
 
     public String getDirectoryId() {
@@ -171,6 +175,32 @@ public class Directory implements Serializable {
         this.companyId = companyId;
     }
 
+    public String getTeamId() {
+        return teamId;
+    }
+
+    public Directory withTeamId(String teamId) {
+        this.setTeamId(teamId);
+        return this;
+    }
+
+    public void setTeamId(String teamId) {
+        this.teamId = teamId;
+    }
+
+    public String getMsGroupIds() {
+        return msGroupIds;
+    }
+
+    public Directory withMsGroupIds(String msGroupIds) {
+        this.setMsGroupIds(msGroupIds);
+        return this;
+    }
+
+    public void setMsGroupIds(String msGroupIds) {
+        this.msGroupIds = msGroupIds;
+    }
+
     @Override
     public boolean equals(Object that) {
         if (this == that) {
@@ -193,7 +223,9 @@ public class Directory implements Serializable {
             && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime()))
             && (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime()))
             && (this.getValidFlag() == null ? other.getValidFlag() == null : this.getValidFlag().equals(other.getValidFlag()))
-            && (this.getCompanyId() == null ? other.getCompanyId() == null : this.getCompanyId().equals(other.getCompanyId()));
+            && (this.getCompanyId() == null ? other.getCompanyId() == null : this.getCompanyId().equals(other.getCompanyId()))
+            && (this.getTeamId() == null ? other.getTeamId() == null : this.getTeamId().equals(other.getTeamId()))
+            && (this.getMsGroupIds() == null ? other.getMsGroupIds() == null : this.getMsGroupIds().equals(other.getMsGroupIds()));
     }
 
     @Override
@@ -211,6 +243,8 @@ public class Directory implements Serializable {
         result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().hashCode());
         result = prime * result + ((getValidFlag() == null) ? 0 : getValidFlag().hashCode());
         result = prime * result + ((getCompanyId() == null) ? 0 : getCompanyId().hashCode());
+        result = prime * result + ((getTeamId() == null) ? 0 : getTeamId().hashCode());
+        result = prime * result + ((getMsGroupIds() == null) ? 0 : getMsGroupIds().hashCode());
         return result;
     }
 
@@ -231,6 +265,8 @@ public class Directory implements Serializable {
         sb.append(", updateTime=").append(updateTime);
         sb.append(", validFlag=").append(validFlag);
         sb.append(", companyId=").append(companyId);
+        sb.append(", teamId=").append(teamId);
+        sb.append(", msGroupIds=").append(msGroupIds);
         sb.append(", serialVersionUID=").append(serialVersionUID);
         sb.append("]");
         return sb.toString();

+ 150 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/model/DirectoryExample.java

@@ -855,6 +855,146 @@ public class DirectoryExample {
             return (Criteria) this;
         }
 
+        public Criteria andTeamIdIsNull() {
+            addCriterion("team_id is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andTeamIdIsNotNull() {
+            addCriterion("team_id is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andTeamIdEqualTo(String value) {
+            addCriterion("team_id =", value, "teamId");
+            return (Criteria) this;
+        }
+
+        public Criteria andTeamIdNotEqualTo(String value) {
+            addCriterion("team_id <>", value, "teamId");
+            return (Criteria) this;
+        }
+
+        public Criteria andTeamIdGreaterThan(String value) {
+            addCriterion("team_id >", value, "teamId");
+            return (Criteria) this;
+        }
+
+        public Criteria andTeamIdGreaterThanOrEqualTo(String value) {
+            addCriterion("team_id >=", value, "teamId");
+            return (Criteria) this;
+        }
+
+        public Criteria andTeamIdLessThan(String value) {
+            addCriterion("team_id <", value, "teamId");
+            return (Criteria) this;
+        }
+
+        public Criteria andTeamIdLessThanOrEqualTo(String value) {
+            addCriterion("team_id <=", value, "teamId");
+            return (Criteria) this;
+        }
+
+        public Criteria andTeamIdLike(String value) {
+            addCriterion("team_id like", value, "teamId");
+            return (Criteria) this;
+        }
+
+        public Criteria andTeamIdNotLike(String value) {
+            addCriterion("team_id not like", value, "teamId");
+            return (Criteria) this;
+        }
+
+        public Criteria andTeamIdIn(List<String> values) {
+            addCriterion("team_id in", values, "teamId");
+            return (Criteria) this;
+        }
+
+        public Criteria andTeamIdNotIn(List<String> values) {
+            addCriterion("team_id not in", values, "teamId");
+            return (Criteria) this;
+        }
+
+        public Criteria andTeamIdBetween(String value1, String value2) {
+            addCriterion("team_id between", value1, value2, "teamId");
+            return (Criteria) this;
+        }
+
+        public Criteria andTeamIdNotBetween(String value1, String value2) {
+            addCriterion("team_id not between", value1, value2, "teamId");
+            return (Criteria) this;
+        }
+
+        public Criteria andMsGroupIdsIsNull() {
+            addCriterion("ms_group_ids is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andMsGroupIdsIsNotNull() {
+            addCriterion("ms_group_ids is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andMsGroupIdsEqualTo(String value) {
+            addCriterion("ms_group_ids =", value, "msGroupIds");
+            return (Criteria) this;
+        }
+
+        public Criteria andMsGroupIdsNotEqualTo(String value) {
+            addCriterion("ms_group_ids <>", value, "msGroupIds");
+            return (Criteria) this;
+        }
+
+        public Criteria andMsGroupIdsGreaterThan(String value) {
+            addCriterion("ms_group_ids >", value, "msGroupIds");
+            return (Criteria) this;
+        }
+
+        public Criteria andMsGroupIdsGreaterThanOrEqualTo(String value) {
+            addCriterion("ms_group_ids >=", value, "msGroupIds");
+            return (Criteria) this;
+        }
+
+        public Criteria andMsGroupIdsLessThan(String value) {
+            addCriterion("ms_group_ids <", value, "msGroupIds");
+            return (Criteria) this;
+        }
+
+        public Criteria andMsGroupIdsLessThanOrEqualTo(String value) {
+            addCriterion("ms_group_ids <=", value, "msGroupIds");
+            return (Criteria) this;
+        }
+
+        public Criteria andMsGroupIdsLike(String value) {
+            addCriterion("ms_group_ids like", value, "msGroupIds");
+            return (Criteria) this;
+        }
+
+        public Criteria andMsGroupIdsNotLike(String value) {
+            addCriterion("ms_group_ids not like", value, "msGroupIds");
+            return (Criteria) this;
+        }
+
+        public Criteria andMsGroupIdsIn(List<String> values) {
+            addCriterion("ms_group_ids in", values, "msGroupIds");
+            return (Criteria) this;
+        }
+
+        public Criteria andMsGroupIdsNotIn(List<String> values) {
+            addCriterion("ms_group_ids not in", values, "msGroupIds");
+            return (Criteria) this;
+        }
+
+        public Criteria andMsGroupIdsBetween(String value1, String value2) {
+            addCriterion("ms_group_ids between", value1, value2, "msGroupIds");
+            return (Criteria) this;
+        }
+
+        public Criteria andMsGroupIdsNotBetween(String value1, String value2) {
+            addCriterion("ms_group_ids not between", value1, value2, "msGroupIds");
+            return (Criteria) this;
+        }
+
         public Criteria andDirectoryIdLikeInsensitive(String value) {
             addCriterion("upper(directory_id) like", value.toUpperCase(), "directoryId");
             return (Criteria) this;
@@ -899,6 +1039,16 @@ public class DirectoryExample {
             addCriterion("upper(company_id) like", value.toUpperCase(), "companyId");
             return (Criteria) this;
         }
+
+        public Criteria andTeamIdLikeInsensitive(String value) {
+            addCriterion("upper(team_id) like", value.toUpperCase(), "teamId");
+            return (Criteria) this;
+        }
+
+        public Criteria andMsGroupIdsLikeInsensitive(String value) {
+            addCriterion("upper(ms_group_ids) like", value.toUpperCase(), "msGroupIds");
+            return (Criteria) this;
+        }
     }
 
     public static class Criteria extends GeneratedCriteria {

+ 19 - 1
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/model/VppMember.java

@@ -42,6 +42,8 @@ public class VppMember implements Serializable {
 
     private String area;
 
+    private String isSso;
+
     private static final long serialVersionUID = 1L;
 
     public String getId() {
@@ -291,6 +293,19 @@ public class VppMember implements Serializable {
         this.area = area;
     }
 
+    public String getIsSso() {
+        return isSso;
+    }
+
+    public VppMember withIsSso(String isSso) {
+        this.setIsSso(isSso);
+        return this;
+    }
+
+    public void setIsSso(String isSso) {
+        this.isSso = isSso;
+    }
+
     @Override
     public boolean equals(Object that) {
         if (this == that) {
@@ -321,7 +336,8 @@ public class VppMember implements Serializable {
             && (this.getResetToken() == null ? other.getResetToken() == null : this.getResetToken().equals(other.getResetToken()))
             && (this.getRole() == null ? other.getRole() == null : this.getRole().equals(other.getRole()))
             && (this.getJob() == null ? other.getJob() == null : this.getJob().equals(other.getJob()))
-            && (this.getArea() == null ? other.getArea() == null : this.getArea().equals(other.getArea()));
+            && (this.getArea() == null ? other.getArea() == null : this.getArea().equals(other.getArea()))
+            && (this.getIsSso() == null ? other.getIsSso() == null : this.getIsSso().equals(other.getIsSso()));
     }
 
     @Override
@@ -347,6 +363,7 @@ public class VppMember implements Serializable {
         result = prime * result + ((getRole() == null) ? 0 : getRole().hashCode());
         result = prime * result + ((getJob() == null) ? 0 : getJob().hashCode());
         result = prime * result + ((getArea() == null) ? 0 : getArea().hashCode());
+        result = prime * result + ((getIsSso() == null) ? 0 : getIsSso().hashCode());
         return result;
     }
 
@@ -375,6 +392,7 @@ public class VppMember implements Serializable {
         sb.append(", role=").append(role);
         sb.append(", job=").append(job);
         sb.append(", area=").append(area);
+        sb.append(", isSso=").append(isSso);
         sb.append(", serialVersionUID=").append(serialVersionUID);
         sb.append("]");
         return sb.toString();

+ 91 - 16
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/model/VppMemberExample.java

@@ -1146,72 +1146,72 @@ public class VppMemberExample {
         }
 
         public Criteria andRoleIsNull() {
-            addCriterion("role is null");
+            addCriterion("`role` is null");
             return (Criteria) this;
         }
 
         public Criteria andRoleIsNotNull() {
-            addCriterion("role is not null");
+            addCriterion("`role` is not null");
             return (Criteria) this;
         }
 
         public Criteria andRoleEqualTo(String value) {
-            addCriterion("role =", value, "role");
+            addCriterion("`role` =", value, "role");
             return (Criteria) this;
         }
 
         public Criteria andRoleNotEqualTo(String value) {
-            addCriterion("role <>", value, "role");
+            addCriterion("`role` <>", value, "role");
             return (Criteria) this;
         }
 
         public Criteria andRoleGreaterThan(String value) {
-            addCriterion("role >", value, "role");
+            addCriterion("`role` >", value, "role");
             return (Criteria) this;
         }
 
         public Criteria andRoleGreaterThanOrEqualTo(String value) {
-            addCriterion("role >=", value, "role");
+            addCriterion("`role` >=", value, "role");
             return (Criteria) this;
         }
 
         public Criteria andRoleLessThan(String value) {
-            addCriterion("role <", value, "role");
+            addCriterion("`role` <", value, "role");
             return (Criteria) this;
         }
 
         public Criteria andRoleLessThanOrEqualTo(String value) {
-            addCriterion("role <=", value, "role");
+            addCriterion("`role` <=", value, "role");
             return (Criteria) this;
         }
 
         public Criteria andRoleLike(String value) {
-            addCriterion("role like", value, "role");
+            addCriterion("`role` like", value, "role");
             return (Criteria) this;
         }
 
         public Criteria andRoleNotLike(String value) {
-            addCriterion("role not like", value, "role");
+            addCriterion("`role` not like", value, "role");
             return (Criteria) this;
         }
 
         public Criteria andRoleIn(List<String> values) {
-            addCriterion("role in", values, "role");
+            addCriterion("`role` in", values, "role");
             return (Criteria) this;
         }
 
         public Criteria andRoleNotIn(List<String> values) {
-            addCriterion("role not in", values, "role");
+            addCriterion("`role` not in", values, "role");
             return (Criteria) this;
         }
 
         public Criteria andRoleBetween(String value1, String value2) {
-            addCriterion("role between", value1, value2, "role");
+            addCriterion("`role` between", value1, value2, "role");
             return (Criteria) this;
         }
 
         public Criteria andRoleNotBetween(String value1, String value2) {
-            addCriterion("role not between", value1, value2, "role");
+            addCriterion("`role` not between", value1, value2, "role");
             return (Criteria) this;
         }
 
@@ -1355,6 +1355,76 @@ public class VppMemberExample {
             return (Criteria) this;
         }
 
+        public Criteria andIsSsoIsNull() {
+            addCriterion("is_sso is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsSsoIsNotNull() {
+            addCriterion("is_sso is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsSsoEqualTo(String value) {
+            addCriterion("is_sso =", value, "isSso");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsSsoNotEqualTo(String value) {
+            addCriterion("is_sso <>", value, "isSso");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsSsoGreaterThan(String value) {
+            addCriterion("is_sso >", value, "isSso");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsSsoGreaterThanOrEqualTo(String value) {
+            addCriterion("is_sso >=", value, "isSso");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsSsoLessThan(String value) {
+            addCriterion("is_sso <", value, "isSso");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsSsoLessThanOrEqualTo(String value) {
+            addCriterion("is_sso <=", value, "isSso");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsSsoLike(String value) {
+            addCriterion("is_sso like", value, "isSso");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsSsoNotLike(String value) {
+            addCriterion("is_sso not like", value, "isSso");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsSsoIn(List<String> values) {
+            addCriterion("is_sso in", values, "isSso");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsSsoNotIn(List<String> values) {
+            addCriterion("is_sso not in", values, "isSso");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsSsoBetween(String value1, String value2) {
+            addCriterion("is_sso between", value1, value2, "isSso");
+            return (Criteria) this;
+        }
+
+        public Criteria andIsSsoNotBetween(String value1, String value2) {
+            addCriterion("is_sso not between", value1, value2, "isSso");
+            return (Criteria) this;
+        }
+
         public Criteria andIdLikeInsensitive(String value) {
             addCriterion("upper(id) like", value.toUpperCase(), "id");
             return (Criteria) this;
@@ -1396,7 +1466,7 @@ public class VppMemberExample {
         }
 
         public Criteria andRoleLikeInsensitive(String value) {
-            addCriterion("upper(role) like", value.toUpperCase(), "role");
+            addCriterion("upper(`role`) like", value.toUpperCase(), "role");
             return (Criteria) this;
         }
 
@@ -1409,6 +1479,11 @@ public class VppMemberExample {
             addCriterion("upper(area) like", value.toUpperCase(), "area");
             return (Criteria) this;
         }
+
+        public Criteria andIsSsoLikeInsensitive(String value) {
+            addCriterion("upper(is_sso) like", value.toUpperCase(), "isSso");
+            return (Criteria) this;
+        }
     }
 
     public static class Criteria extends GeneratedCriteria {
@@ -1502,4 +1577,4 @@ public class VppMemberExample {
             this(condition, value, secondValue, null);
         }
     }
-}
+}

+ 9 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/pojo/MSGroup.java

@@ -0,0 +1,9 @@
+package cn.kdan.pdf.tech.core.pojo;
+
+import lombok.Data;
+
+@Data
+public class MSGroup {
+    private String id;
+    private String displayName;
+}

+ 29 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/pojo/dto/AddSyncDTO.java

@@ -0,0 +1,29 @@
+package cn.kdan.pdf.tech.core.pojo.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import java.util.List;
+
+@Data
+public class AddSyncDTO {
+
+    @NotEmpty(message = "directoryId cannot be blank")
+    private String directoryId;
+    @NotEmpty(message = "applicationID cannot be blank")
+    private String applicationID;
+    @NotEmpty(message = "clientSecrets cannot be blank")
+    private String clientSecrets;
+    @NotEmpty(message = "tenantId cannot be blank")
+    private String tenantId;
+    @NotEmpty(message = "scope cannot be blank")
+    private String scope;
+    /**
+     * 分配产品信息
+     */
+    private List<CreateTeamDTO.Product> productList;
+    /**
+     * scope为指定组的时候
+     */
+    private List<String> groupIds;
+}

+ 2 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/pojo/dto/CreateTeamDTO.java

@@ -23,6 +23,8 @@ public class CreateTeamDTO {
      */
     private String teamDescription;
 
+    private String teamId;
+
     /**
      * 团队管理员id
      */

+ 1 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/pojo/dto/DirectoryUpdateDTO.java

@@ -10,4 +10,5 @@ public class DirectoryUpdateDTO {
     private String name;
     @NotBlank
     private String directoryId;
+
 }

+ 19 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/pojo/dto/ScheduleSettingDTO.java

@@ -0,0 +1,19 @@
+package cn.kdan.pdf.tech.core.pojo.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import java.util.List;
+
+@Data
+public class ScheduleSettingDTO {
+    /**
+     * 同步时间点
+     */
+    private String time;
+    /**
+     * 同步类型
+     */
+    private String type;
+    private String directoryId;
+}

+ 33 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/pojo/vo/SSODeletedMemberVO.java

@@ -0,0 +1,33 @@
+package cn.kdan.pdf.tech.core.pojo.vo;
+
+import cn.kdan.pdf.tech.core.converter.SSOMemberStatusConverter;
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.ColumnWidth;
+import com.alibaba.excel.annotation.write.style.ContentStyle;
+import com.alibaba.excel.enums.BooleanEnum;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author tangxiangan
+ */
+@Data
+@ContentStyle(
+        wrapped = BooleanEnum.TRUE)
+public class SSODeletedMemberVO implements Serializable {
+
+    @ExcelIgnore
+    private String id;
+
+    @ExcelProperty(value = "Member Name")
+    @ColumnWidth(34)
+    private String fullName;
+
+    @ExcelProperty(value = "Email")
+    @ColumnWidth(34)
+    private String email;
+
+
+}

+ 27 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/pojo/vo/SSOMemberLicenseVO.java

@@ -0,0 +1,27 @@
+package cn.kdan.pdf.tech.core.pojo.vo;
+
+
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @author tangxiangan
+ */
+@Data
+public class SSOMemberLicenseVO {
+
+    private String id;
+
+    private String fullName;
+
+    private String email;
+
+    private String validFlag;
+
+    private String updatedAt;
+
+    private String cdkey;
+
+    private Date endUpAt;
+}

+ 42 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/pojo/vo/SSOMemberVO.java

@@ -0,0 +1,42 @@
+package cn.kdan.pdf.tech.core.pojo.vo;
+
+import cn.kdan.pdf.tech.core.converter.SSOMemberStatusConverter;
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.ColumnWidth;
+import com.alibaba.excel.annotation.write.style.ContentStyle;
+import com.alibaba.excel.enums.BooleanEnum;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author tangxiangan
+ */
+@Data
+@ContentStyle(
+        wrapped = BooleanEnum.TRUE)
+public class SSOMemberVO implements Serializable {
+
+    @ExcelIgnore
+    private String id;
+
+    @ExcelProperty(value = "Member Name")
+    @ColumnWidth(34)
+    private String fullName;
+
+    @ExcelProperty(value = "Email")
+    @ColumnWidth(34)
+    private String email;
+
+
+    @ExcelProperty(converter = SSOMemberStatusConverter.class,value = "Status")
+    @ColumnWidth(34)
+    private String validFlag;
+
+    @ExcelProperty(value = "LoginTime")
+    @ColumnWidth(34)
+    private String updatedAt;
+
+
+}

+ 5 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/pojo/vo/VppTeamMemberVO.java

@@ -45,8 +45,13 @@ public class VppTeamMemberVO implements Serializable {
 
     @ExcelIgnore
     private String createdAt;
+    @ExcelIgnore
+    private String updatedAt;
 
     @ExcelIgnore
     private String codes;
 
+    @ExcelIgnore
+    private Integer isSso;
+
 }

+ 6 - 2
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/DirectoryService.java

@@ -25,12 +25,16 @@ public interface DirectoryService {
      * 删除目录
      * @param directoryId directoryId
      */
-    void  delete (String directoryId);
+    void delete(String directoryId);
 
     /**
      * 更新
+     *
      * @param directoryUpdateDTO directoryUpdateDTO
      */
-    void  update (DirectoryUpdateDTO directoryUpdateDTO);
+    void update(DirectoryUpdateDTO directoryUpdateDTO);
 
+    Directory getById(String directoryId);
+
+    void updateSelective(Directory directory);
 }

+ 4 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/DirectorySyncService.java

@@ -12,4 +12,8 @@ public interface DirectorySyncService {
      * @return List
      */
     List<DirectorySync> listByDirectoryId(String directoryId);
+
+    void create(DirectorySync directorySync);
+
+    void update(DirectorySync directorySync);
 }

+ 3 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/ProductService.java

@@ -46,4 +46,7 @@ public interface ProductService {
      * @return
      */
     List<ProductListVO> listWithAll();
+
+
+    Products getByCode(String productCode);
 }

+ 13 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/ScheduleSettingService.java

@@ -1,6 +1,7 @@
 package cn.kdan.pdf.tech.core.service;
 
 import cn.kdan.pdf.tech.core.model.ScheduleSetting;
+import cn.kdan.pdf.tech.core.pojo.dto.ScheduleSettingDTO;
 
 import java.util.List;
 
@@ -12,4 +13,16 @@ public interface ScheduleSettingService {
      * @return List
      */
     List<ScheduleSetting> listByDirectoryId(String directoryId);
+
+    /**
+     * 查询所有配置创建定时任务
+     * @return
+     */
+    List<ScheduleSetting> list();
+
+    /**
+     * 添加同步and修改同步设置
+     * @param scheduleSettingDTO scheduleSettingDTO
+     */
+    void syncSetting(ScheduleSettingDTO scheduleSettingDTO);
 }

+ 29 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/SyncService.java

@@ -0,0 +1,29 @@
+package cn.kdan.pdf.tech.core.service;
+
+import cn.kdan.pdf.tech.core.pojo.MSGroup;
+import cn.kdan.pdf.tech.core.pojo.dto.AddSyncDTO;
+
+import java.util.List;
+
+public interface SyncService {
+    /**
+     * 添加同步设置
+     * @param syncDTO syncDTO
+     */
+    void addSyncSettings(AddSyncDTO syncDTO);
+
+    /**
+     * 开始同步
+     * @param directoryId directoryId
+     */
+    void startSync(String directoryId);
+
+    /**
+     * 获取微软的组列表
+     * @param clientId clientId
+     * @param tenantId tenantId
+     * @param clientSecret clientSecret
+     * @return
+     */
+    List<MSGroup> getGroupList(String clientId, String tenantId, String clientSecret);
+}

+ 7 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/VppLicenseCodeService.java

@@ -161,4 +161,11 @@ public interface VppLicenseCodeService {
      * @param licenseCodeId 序列码id
      */
     void disable(String licenseCodeId);
+
+    /**
+     * 获取用户对于某个产品的序列码
+     * @param id 用户id
+     * @param productCode 产品code
+     */
+    LicenseCodes getByMemberId(String id, String productCode);
 }

+ 7 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/VppMemberService.java

@@ -32,6 +32,13 @@ public interface VppMemberService extends BeanConverter<VppMember, UserInfo> {
      */
     VppMember getByAccount(String account);
 
+    /**
+     * 获取sso用户
+     * @param account account
+     * @return
+     */
+    VppMember getByAccountSSO(String account);
+
     /**
      * 注册 超级管理员和管理员
      *

+ 25 - 2
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/VppRTeamMemberRoleService.java

@@ -145,7 +145,7 @@ public interface VppRTeamMemberRoleService {
      * @param queryString queryString
      * @return PageInfo
      */
-    PageInfo<VppTeamMemberVO> pageForMember(Integer page, Integer pageSize, String teamId, String status, String productCode, String queryString);
+    PageInfo<VppTeamMemberVO> pageForMember(Integer page, Integer pageSize, String teamId, String status, String productCode, String queryString, String isSso);
 
     /**
      *  列表用于导出
@@ -155,7 +155,7 @@ public interface VppRTeamMemberRoleService {
      * @param queryString
      * @return
      */
-    List<VppTeamMemberVO> listForMember(String teamId, String status, String productCode, String queryString);
+    List<VppTeamMemberVO> listForMember(String teamId, String status, String productCode, String queryString, String isSso);
 
     /**
      * 获取成员所在团队id
@@ -178,4 +178,27 @@ public interface VppRTeamMemberRoleService {
      * @return List
      */
     List<VppRTeamMemberRole> listByTeamIdWithoutSuperAdmin(String teamId);
+
+    /**
+     * 删除sso用户
+     * @param memberId 用户id
+     */
+    void removeSSOMembers(String memberId);
+
+    /**
+     * 吊销sso用户(暂时冻结登录和使用)
+     * @param memberId 用户id
+     */
+    void revokeSSOMember(String memberId);
+
+    /**
+     * 还原用户
+     * @param memberId 用户id
+     */
+    void reductionSSOMember(String memberId);
+    /**
+     * 取消吊销用户
+     * @param memberId 用户id
+     */
+    void accessSSOMember(String memberId);
 }

+ 46 - 2
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/impl/DirectoryServiceImpl.java

@@ -1,26 +1,46 @@
 package cn.kdan.pdf.tech.core.service.impl;
 
+import cn.kdan.pdf.tech.core.constant.SSOConstant;
+import cn.kdan.pdf.tech.core.constant.VppTeamConstant;
+import cn.kdan.pdf.tech.core.enums.RoleEnum;
+import cn.kdan.pdf.tech.core.enums.ScpoeEnum;
 import cn.kdan.pdf.tech.core.mapper.DirectoryMapper;
 import cn.kdan.pdf.tech.core.model.*;
+import cn.kdan.pdf.tech.core.pojo.MSGroup;
+import cn.kdan.pdf.tech.core.pojo.dto.AddSyncDTO;
+import cn.kdan.pdf.tech.core.pojo.dto.CreateTeamDTO;
 import cn.kdan.pdf.tech.core.pojo.dto.DirectoryCreateDTO;
 import cn.kdan.pdf.tech.core.pojo.dto.DirectoryUpdateDTO;
 import cn.kdan.pdf.tech.core.pojo.vo.DirectoryVO;
+import cn.kdan.pdf.tech.core.pojo.vo.VppTeamMemberVO;
 import cn.kdan.pdf.tech.core.service.*;
+import com.azure.identity.ClientSecretCredential;
+import com.azure.identity.ClientSecretCredentialBuilder;
+import com.microsoft.graph.models.Group;
+import com.microsoft.graph.models.GroupCollectionResponse;
+import com.microsoft.graph.models.User;
+import com.microsoft.graph.models.UserCollectionResponse;
+import com.microsoft.graph.serviceclient.GraphServiceClient;
 import enums.ValidStatusEnum;
 import exception.BackendRuntimeException;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
 import utils.CommonUtils;
 
 import javax.annotation.Resource;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
+import java.util.stream.Collectors;
 
 @Service
 @Slf4j
+@Transactional
 public class DirectoryServiceImpl implements DirectoryService {
     @Resource
     private DirectoryMapper directoryMapper;
@@ -32,6 +52,10 @@ public class DirectoryServiceImpl implements DirectoryService {
     private ScheduleSettingService scheduleSettingService;
     @Resource
     private DirectorySyncService directorySyncService;
+    @Resource
+    private VppTeamService teamService;
+    @Resource
+    private VppRTeamMemberRoleService vppRTeamMemberRoleService;
     @Override
     public List<DirectoryVO> list() {
         //获取当前登录用户公司id
@@ -91,7 +115,27 @@ public class DirectoryServiceImpl implements DirectoryService {
         directoryMapper.updateByPrimaryKeySelective(directory);
     }
 
-    public List<Directory> listByCompanyId(String companyId) {
+
+    /**
+     * 根据id获取目录
+     * @param directoryId  directoryId
+     * @return Directory
+     */
+    @Override
+    public Directory getById(String directoryId) {
+       Directory directory =  directoryMapper.selectByPrimaryKey(directoryId);
+       if(ObjectUtils.isEmpty(directory)){
+           throw new BackendRuntimeException(SSOConstant.DIRECTORY_NOT_EXIST);
+       }
+       return directory;
+    }
+
+    @Override
+    public void updateSelective(Directory directory) {
+        directoryMapper.updateByPrimaryKeySelective(directory);
+    }
+
+    private List<Directory> listByCompanyId(String companyId) {
         DirectoryExample example = new DirectoryExample();
         example.createCriteria().andCompanyIdEqualTo(companyId).andValidFlagEqualTo(ValidStatusEnum.VALID.value());
         return directoryMapper.selectByExample(example);
@@ -101,7 +145,7 @@ public class DirectoryServiceImpl implements DirectoryService {
         example.createCriteria().andNameEqualTo(name).andValidFlagEqualTo(ValidStatusEnum.VALID.value());
         List<Directory> list = directoryMapper.selectByExample(example);
         if (!CollectionUtils.isEmpty(list)) {
-            throw new BackendRuntimeException("Directory name already exists");
+            throw new BackendRuntimeException(SSOConstant.DIRECTORY_EXIST);
         }
     }
 

+ 10 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/impl/DirectorySyncServiceImpl.java

@@ -23,4 +23,14 @@ public class DirectorySyncServiceImpl implements DirectorySyncService {
         List<DirectorySync> list = directorySyncMapper.selectByExample(syncExample);
         return CollectionUtils.isEmpty(list) ? new ArrayList<>() : list;
     }
+
+    @Override
+    public void create(DirectorySync directorySync) {
+        directorySyncMapper.insert(directorySync);
+    }
+
+    @Override
+    public void update(DirectorySync directorySync) {
+        directorySyncMapper.updateByPrimaryKey(directorySync);
+    }
 }

+ 11 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/impl/DomainServiceImpl.java

@@ -124,6 +124,11 @@ public class DomainServiceImpl implements DomainService {
         return domain;
     }
 
+    /**
+     * 验证域名
+     * @param domain    域名
+     * @param verifyCode 验证code
+     */
     private void checkDns(String domain, String verifyCode){
         boolean found = false;
         try {
@@ -151,6 +156,12 @@ public class DomainServiceImpl implements DomainService {
         }
     }
 
+    /**
+     * 验证域名
+     * @param domain    域名
+     * @param fileName 文件名
+     * @param fileContent 文件内容
+     */
     private void checkHttp(String domain, String fileName, String fileContent){
         String url = "http://" + domain + "/" + fileName;
         try {

+ 8 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/impl/ProductServiceImpl.java

@@ -80,4 +80,12 @@ public class ProductServiceImpl implements ProductService {
         VppMember member = vppMemberService.getCurrentUser();
         return productMapper.listWithAll(member.getCompanyId());
     }
+
+    @Override
+    public Products getByCode(String productCode) {
+        ProductsExample productsExample = new ProductsExample();
+        productsExample.createCriteria().andCodeEqualTo(productCode);
+        List<Products> products = productMapper.selectByExample(productsExample);
+        return  CollectionUtils.isEmpty(products) ? null : products.get(0);
+    }
 }

+ 73 - 1
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/impl/ScheduleSettingServiceImpl.java

@@ -1,21 +1,32 @@
 package cn.kdan.pdf.tech.core.service.impl;
 
+import cn.kdan.pdf.tech.core.enums.ScheduleSettingTypeEnum;
 import cn.kdan.pdf.tech.core.mapper.ScheduleSettingMapper;
 import cn.kdan.pdf.tech.core.model.ScheduleSetting;
 import cn.kdan.pdf.tech.core.model.ScheduleSettingExample;
+import cn.kdan.pdf.tech.core.pojo.dto.ScheduleSettingDTO;
 import cn.kdan.pdf.tech.core.service.ScheduleSettingService;
+import cn.kdan.pdf.tech.core.service.SyncService;
+import cn.kdan.pdf.tech.core.utils.QuartzUtils;
+import cn.kdan.pdf.tech.core.utils.SyncJob;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
+import utils.CommonUtils;
 
+import javax.annotation.PostConstruct;
 import javax.annotation.Resource;
 import java.util.ArrayList;
 import java.util.List;
 
 @Service
+@Slf4j
 public class ScheduleSettingServiceImpl implements ScheduleSettingService {
     @Resource
     private ScheduleSettingMapper scheduleSettingMapper;
-
+    @Resource
+    private SyncService syncService;
     @Override
     public List<ScheduleSetting> listByDirectoryId(String directoryId) {
         ScheduleSettingExample scheduleSettingExample = new ScheduleSettingExample();
@@ -23,4 +34,65 @@ public class ScheduleSettingServiceImpl implements ScheduleSettingService {
         List<ScheduleSetting> list = scheduleSettingMapper.selectByExample(scheduleSettingExample);
         return CollectionUtils.isEmpty(list) ? new ArrayList<>() : list;
     }
+
+    @Override
+    public List<ScheduleSetting> list() {
+        ScheduleSettingExample scheduleSettingExample = new ScheduleSettingExample();
+        scheduleSettingExample.createCriteria().andTypeNotEqualTo(ScheduleSettingTypeEnum.SYNC_NOW.value());
+        List<ScheduleSetting> list = scheduleSettingMapper.selectByExample(scheduleSettingExample);
+        return CollectionUtils.isEmpty(list) ? new ArrayList<>() : list;
+    }
+
+    /**
+     * 同步设置
+     * @param scheduleSettingDTO
+     */
+    @Override
+    public void syncSetting(ScheduleSettingDTO scheduleSettingDTO) {
+        List<ScheduleSetting> list = listByDirectoryId(scheduleSettingDTO.getDirectoryId());
+        ScheduleSetting scheduleSetting = new ScheduleSetting();
+        BeanUtils.copyProperties(scheduleSettingDTO, scheduleSetting);
+        if(scheduleSettingDTO.getType().equals(ScheduleSettingTypeEnum.SYNC_NOW.value())){
+            syncService.startSync(scheduleSetting.getDirectoryId());
+            //如果之前不为空,现在是立即同步,那么要把以前的定时任务给删掉
+            if(!CollectionUtils.isEmpty(list)){
+                QuartzUtils.deleteJob("syncJob" + list.get(0).getScheduleSettingId(),"syncJobGroup");
+            }
+        }else {
+            //先判断是否已有配置
+            if(CollectionUtils.isEmpty(list)){
+                scheduleSetting.setScheduleSettingId(CommonUtils.generateId());
+                scheduleSettingMapper.insertSelective(scheduleSetting);
+                //创建定时任务
+                QuartzUtils.scheduleJob("syncJob" + scheduleSetting.getScheduleSettingId(),"syncJobGroup", SyncJob.class,
+                        "syncTrigger_" + scheduleSetting.getScheduleSettingId(),"syncTriggerGroup",
+                        "0 * * * *",scheduleSetting.getDirectoryId() );
+            }else {
+                list.get(0).setTime(scheduleSettingDTO.getTime());
+                list.get(0).setType(scheduleSettingDTO.getType());
+                scheduleSettingMapper.updateByPrimaryKeySelective(list.get(0));
+                QuartzUtils.rescheduleJob("syncTrigger_" + scheduleSetting.getScheduleSettingId(), "syncTriggerGroup", "0 * * * *",scheduleSetting);
+            }
+        }
+    }
+
+    @PostConstruct
+    public void initJob() {
+        log.info("initJob start:--------------");
+        List<ScheduleSetting> list = list();
+        for (ScheduleSetting scheduleSetting : list) {
+            if (scheduleSetting.getType().equals(ScheduleSettingTypeEnum.PER_HOUR.value())) {
+                //创建定时任务
+                QuartzUtils.scheduleJob("syncJob" + scheduleSetting.getScheduleSettingId(), "syncJobGroup", SyncJob.class,
+                        "syncTrigger_" + scheduleSetting.getScheduleSettingId(), "syncTriggerGroup",
+                        "0 * * * *", scheduleSetting.getDirectoryId());
+            } else if (scheduleSetting.getType().equals(ScheduleSettingTypeEnum.SPECIFIED_TIME_EVERY_DAY.value())) {
+                //创建定时任务
+                QuartzUtils.scheduleJob("syncJob" + scheduleSetting.getScheduleSettingId(), "syncJobGroup", SyncJob.class,
+                        "syncTrigger_" + scheduleSetting.getScheduleSettingId(), "syncTriggerGroup",
+                        QuartzUtils.generateCronExpression(scheduleSetting.getTime()), scheduleSetting.getDirectoryId());
+            }
+        }
+        log.info("initJob finish:--------------");
+    }
 }

+ 281 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/impl/SyncServiceImpl.java

@@ -0,0 +1,281 @@
+package cn.kdan.pdf.tech.core.service.impl;
+
+import cn.kdan.pdf.tech.core.constant.SSOConstant;
+import cn.kdan.pdf.tech.core.constant.VppTeamConstant;
+import cn.kdan.pdf.tech.core.enums.RoleEnum;
+import cn.kdan.pdf.tech.core.enums.ScpoeEnum;
+import cn.kdan.pdf.tech.core.enums.SyncStatusEnum;
+import cn.kdan.pdf.tech.core.enums.SyncUserEnum;
+import cn.kdan.pdf.tech.core.model.*;
+import cn.kdan.pdf.tech.core.pojo.MSGroup;
+import cn.kdan.pdf.tech.core.pojo.dto.AddSyncDTO;
+import cn.kdan.pdf.tech.core.pojo.dto.CreateTeamDTO;
+import cn.kdan.pdf.tech.core.pojo.vo.VppTeamMemberVO;
+import cn.kdan.pdf.tech.core.service.*;
+import com.azure.identity.ClientSecretCredential;
+import com.azure.identity.ClientSecretCredentialBuilder;
+import com.microsoft.graph.models.Group;
+import com.microsoft.graph.models.GroupCollectionResponse;
+import com.microsoft.graph.models.User;
+import com.microsoft.graph.models.UserCollectionResponse;
+import com.microsoft.graph.serviceclient.GraphServiceClient;
+
+import enums.ValidStatusEnum;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
+import utils.CommonUtils;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Service
+@Slf4j
+@Transactional
+public class SyncServiceImpl implements SyncService {
+    @Resource
+    private DirectoryService directoryService;
+    @Resource
+    private VppMemberService vppMemberService;
+    @Resource
+    private VppTeamService teamService;
+    @Resource
+    private VppRTeamMemberRoleService vppRTeamMemberRoleService;
+    @Resource
+    private DirectorySyncService directorySyncService;
+
+    @Override
+    public void addSyncSettings(AddSyncDTO syncDTO) {
+        //根据id获取目录
+        Directory directory = directoryService.getById(syncDTO.getDirectoryId());
+        //修改数据库
+        directory.setApplicationId(syncDTO.getApplicationID());
+        directory.setClientSecrets(syncDTO.getClientSecrets());
+        directory.setScope(syncDTO.getScope());
+        directory.setTenantId(syncDTO.getTenantId());
+        directory.setUpdateTime(new Date());
+        if (CollectionUtils.isEmpty(syncDTO.getGroupIds())) {
+            directory.setMsGroupIds(listToString(syncDTO.getGroupIds()));
+        }
+        directoryService.updateSelective(directory);
+        //创建一个目录的默认团队,判断是否有默认团队了
+        String teamId = directory.getTeamId();
+        VppTeam team = teamService.getById(teamId);
+        if (ObjectUtils.isEmpty(team)) {
+            //没有团队则先创建默认团队
+            teamId = CommonUtils.generateId();
+            CreateTeamDTO dto = new CreateTeamDTO();
+            dto.setTeamName(directory.getName());
+            dto.setTeamDescription("sync");
+            dto.setProductList(syncDTO.getProductList());
+            dto.setTeamId(teamId);
+            //创建团队
+            teamService.createTeam(dto);
+            //绑定目录和团队
+            directory.setTeamId(teamId);
+            directoryService.updateSelective(directory);
+        }
+        String syncId = startLog(directory);
+        if (syncDTO.getScope().equals(ScpoeEnum.ALL.value())) {
+            //同步全部
+            syncMSUserAll(directory);
+        }
+        if (syncDTO.getScope().equals(ScpoeEnum.SPECIFY.value())) {
+            //同步特定
+            syncMSUserSpecifyGroup(directory);
+        }
+        endLog(syncId);
+    }
+
+    @Override
+    public void startSync(String directoryId) {
+        //根据id获取目录
+        Directory directory = directoryService.getById(directoryId);
+        //修改数据库
+        directory.setApplicationId(directory.getApplicationId());
+        directory.setClientSecrets(directory.getClientSecrets());
+        directory.setScope(directory.getScope());
+        directory.setTenantId(directory.getTenantId());
+        directory.setUpdateTime(new Date());
+        directoryService.updateSelective(directory);
+        //创建一个目录的默认团队,判断是否有默认团队了
+        String teamId = directory.getTeamId();
+        VppTeam team = teamService.getById(teamId);
+        if (ObjectUtils.isEmpty(team)) {
+            log.error("TEAM_NOT_EXIST:{}", teamId);
+            throw new RuntimeException(VppTeamConstant.TEAM_NOT_EXIST);
+        }
+        String syncId = startLog(directory);
+        if (directory.getScope().equals(ScpoeEnum.ALL.value())) {
+            //同步全部
+            syncMSUserAll(directory);
+        }
+        if (directory.getScope().equals(ScpoeEnum.SPECIFY.value())) {
+            //同步特定
+            syncMSUserSpecifyGroup(directory);
+        }
+        endLog(syncId);
+    }
+
+    /**
+     * 同步MS用户同步所有
+     *
+     * @param directory 目录对象
+     */
+    public void syncMSUserAll(Directory directory) {
+        String companyId = directory.getCompanyId();
+        String teamId = directory.getTeamId();
+        final String[] scopes = new String[]{SSOConstant.GRAPH_SCOPE};
+        final ClientSecretCredential credential = new ClientSecretCredentialBuilder()
+                .clientId(directory.getApplicationId())
+                .tenantId(directory.getTenantId())
+                .clientSecret(directory.getClientSecrets())
+                .build();
+        final GraphServiceClient graphClient = new GraphServiceClient(credential, scopes);
+
+        UserCollectionResponse userResponse = graphClient.users().get();
+        List<User> users = userResponse.getValue();
+        List<String> microsoftEmails = users.stream().map(User::getUserPrincipalName).collect(Collectors.toList());
+
+        handleUsersData(users, microsoftEmails, companyId, teamId);
+    }
+
+    private void endLog(String syncId) {
+        DirectorySync directorySync = new DirectorySync();
+        directorySync.setStatus(SyncStatusEnum.SYNC_FINISHED.value());
+        directorySync.setSyncTime(new Date());
+        directorySync.setDirectorySyncId(syncId);
+        directorySyncService.create(directorySync);
+    }
+
+    private String startLog(Directory directory) {
+        DirectorySync directorySync = new DirectorySync();
+        String syncId =  CommonUtils.generateId();
+        directorySync.setDirectoryId(directory.getDirectoryId());
+        directorySync.setStatus(SyncStatusEnum.SYNC_ING.value());
+        directorySync.setSyncTime(new Date());
+        directorySync.setDirectorySyncId(CommonUtils.generateId());
+        directorySyncService.create(directorySync);
+        return syncId;
+    }
+
+    /**
+     * 同步MS用户同步特定
+     *
+     * @param directory 目录对象
+     */
+    public void syncMSUserSpecifyGroup(Directory directory) {
+        String companyId = directory.getCompanyId();
+        String teamId = directory.getTeamId();
+        List<String> groupIds = stringToList(directory.getMsGroupIds());
+        final String[] scopes = new String[]{SSOConstant.GRAPH_SCOPE};
+        final ClientSecretCredential credential = new ClientSecretCredentialBuilder()
+                .clientId(directory.getApplicationId())
+                .tenantId(directory.getTenantId())
+                .clientSecret(directory.getClientSecrets())
+                .build();
+        final GraphServiceClient graphClient = new GraphServiceClient(credential, scopes);
+
+        List<User> users = new ArrayList<>();
+        groupIds.forEach(groupId -> {
+            Group group = graphClient.groups().byGroupId(groupId).get(requestConfiguration -> {
+                requestConfiguration.queryParameters.expand = new String[]{"members"};
+            });
+            group.getMembers().forEach(member -> {
+                if (member instanceof User) {
+                    users.add((User) member);
+                }
+            });
+        });
+
+        List<String> microsoftEmails = users.stream().map(User::getUserPrincipalName).collect(Collectors.toList());
+
+        handleUsersData(users, microsoftEmails, companyId, teamId);
+    }
+
+    /**
+     * 对比微软用户和我们指定组用户的差别,进行同步
+     *
+     * @param users           users
+     * @param microsoftEmails microsoftEmails
+     * @param companyId       companyId
+     * @param teamId          teamId
+     */
+    private void handleUsersData(List<User> users, List<String> microsoftEmails, String companyId, String teamId) {
+        for (User user : users) {
+            String email = user.getUserPrincipalName();
+            String name = user.getDisplayName();
+            String id = user.getId();
+
+            VppMember member = vppMemberService.getByAccount(email);
+
+            if (ObjectUtils.isEmpty(member)) {
+                VppMember newMember = new VppMember().withId(id)
+                        .withFullName(name)
+                        .withEmail(email)
+                        .withValidFlag(ValidStatusEnum.VALID.value())
+                        .withCreatedAt(new Date())
+                        .withUpdatedAt(new Date())
+                        .withSubscriberType(0)
+                        .withRole(RoleEnum.TEAM_MEMBER.code())
+                        .withIsSso(SyncUserEnum.SSO.value())
+                        .withCompanyId(companyId);
+                vppMemberService.insert(newMember);
+
+                VppRTeamMemberRole vppRTeamMemberRole = new VppRTeamMemberRole()
+                        .withMemberId(id)
+                        .withRoleId(RoleEnum.TEAM_MEMBER.code())
+                        .withTeamId(teamId)
+                        .withId(CommonUtils.generateId());
+                vppRTeamMemberRoleService.create(vppRTeamMemberRole);
+            } else {
+                member.setFullName(name);
+                vppMemberService.update(member);
+            }
+        }
+
+        List<VppTeamMemberVO> localMembers = vppRTeamMemberRoleService.listForMember(teamId, RoleEnum.TEAM_MEMBER.code(), null, null, "1");
+        localMembers.stream()
+                .filter(member -> !microsoftEmails.contains(member.getEmail()))
+                .forEach(member -> vppRTeamMemberRoleService.deleteMember(member.getId()));
+    }
+
+    @Override
+    public List<MSGroup> getGroupList(String clientId, String tenantId, String clientSecret) {
+        String[] scopes = new String[]{SSOConstant.GRAPH_SCOPE};
+        ClientSecretCredential credential = new ClientSecretCredentialBuilder()
+                .clientId(clientId).tenantId(tenantId).clientSecret(clientSecret).build();
+        GraphServiceClient graphClient = new GraphServiceClient(credential, scopes);
+        try {
+            GroupCollectionResponse groupResponse = graphClient.groups().get();
+            List<Group> groups = groupResponse.getValue();
+            List<MSGroup> msGroups = new ArrayList<>();
+            groups.forEach(group -> {
+                String name = group.getDisplayName();
+                String id = group.getId();
+                MSGroup msGroup = new MSGroup();
+                msGroup.setId(id);
+                msGroup.setDisplayName(name);
+                msGroups.add(msGroup);
+            });
+            return msGroups;
+        } catch (Exception e) {
+            return new ArrayList<>();
+        }
+    }
+
+    public String listToString(List<String> stringList) {
+        return String.join(",", stringList);
+    }
+
+    public List<String> stringToList(String str) {
+        return Arrays.asList(str.split(","));
+    }
+
+}

+ 2 - 1
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/impl/VppDeviceServiceImpl.java

@@ -14,6 +14,7 @@ import cn.kdan.pdf.tech.core.utils.ThreadPoolSingleUtil;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import constant.CommonConstant;
+import enums.ValidStatusEnum;
 import exception.BackendRuntimeException;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang.StringUtils;
@@ -157,7 +158,7 @@ public class VppDeviceServiceImpl implements VppDeviceService {
 
         log.info("send cancel email!");
         ThreadPoolSingleUtil.getInstance().excute(() -> {
-            if(!ObjectUtils.isEmpty(vppMember)){
+            if(!ObjectUtils.isEmpty(vppMember)&&!vppMember.getIsSso().equals(ValidStatusEnum.VALID.value())){
                 Subscriptions subscriptions = subscriptionService.getById(code.getSubscriptionId());
                 Products product = productService.getById(subscriptions.getProductId());
                 String helpLink = vppLicenseCodeServiceImpl.getHelpLink(product.getCode());

+ 37 - 19
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/impl/VppLicenseCodeServiceImpl.java

@@ -20,6 +20,7 @@ import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import constant.CommonConstant;
+import enums.ValidStatusEnum;
 import exception.BackendRuntimeException;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang.StringUtils;
@@ -256,18 +257,21 @@ public class VppLicenseCodeServiceImpl implements VppLicenseCodeService {
                     }
                 }
                 VppMember vppMember = vppMemberService.getById(key);
-                // 根据平台发送序列码授权邮件
-                log.info("根据平台发送序列码授权邮件:productWin{};cdKeyWin:{};platformType:{}", productName, cdKey, platformType);
-                switch(platformType) {
-                    case 1:
-                        sendAssignEmail(cdKey, productName, vppMember, winDownloadUrl, winHelpUrl);
-                        break;
-                    case 2:
-                        sendAssignEmail(cdKey, productName, vppMember, macDownloadUrl, macHelpUrl);
-                        break;
-                    case 3:
-                        sendAssignEmail(cdKey, productName, vppMember, platformDownloadUrl, platformHelpUrl);
-                        break;
+                //非单点登录用户才发送邮件
+                if(!vppMember.getIsSso().equals(ValidStatusEnum.VALID.value())){
+                    // 根据平台发送序列码授权邮件
+                    log.info("根据平台发送序列码授权邮件:productWin{};cdKeyWin:{};platformType:{}", productName, cdKey, platformType);
+                    switch(platformType) {
+                        case 1:
+                            sendAssignEmail(cdKey, productName, vppMember, winDownloadUrl, winHelpUrl);
+                            break;
+                        case 2:
+                            sendAssignEmail(cdKey, productName, vppMember, macDownloadUrl, macHelpUrl);
+                            break;
+                        case 3:
+                            sendAssignEmail(cdKey, productName, vppMember, platformDownloadUrl, platformHelpUrl);
+                            break;
+                    }
                 }
             });
         });
@@ -378,13 +382,15 @@ public class VppLicenseCodeServiceImpl implements VppLicenseCodeService {
         licenseCodeMapper.updateByPrimaryKey(vppLicenseCode);
         // 解绑激活设备
         vppDeviceService.unBindByMemberId(null, Collections.singletonList(vppLicenseCode.getCdkey()));
-        // 发送邮件
-        ThreadPoolSingleUtil.getInstance().excute(() -> {
-            String text = String.format(CaptchaActionEnum.CANCEL_LICENSE_ASSIGN.text(), vppMember.getEmail(), ProductNameEnum.getEnumByDatabaseName(products.getName()).viewName(), products.getName(), user.getEmail());
-            // 替换图片动态地址和取消订阅链接
-            text = text.replace("emailImagesUrl", emailImagesUrl).replace("cancelEmailUrl", readerproUrl + "/unsubscribe?email=" + vppMember.getEmail());
-            emailUtils.sendMail(CaptchaActionEnum.CANCEL_LICENSE_ASSIGN.subject(), text, Collections.singletonList(vppMember.getEmail()));
-        });
+        if (!vppMember.getIsSso().equals(ValidStatusEnum.VALID.value())){
+            // 发送邮件
+            ThreadPoolSingleUtil.getInstance().excute(() -> {
+                String text = String.format(CaptchaActionEnum.CANCEL_LICENSE_ASSIGN.text(), vppMember.getEmail(), ProductNameEnum.getEnumByDatabaseName(products.getName()).viewName(), products.getName(), user.getEmail());
+                // 替换图片动态地址和取消订阅链接
+                text = text.replace("emailImagesUrl", emailImagesUrl).replace("cancelEmailUrl", readerproUrl + "/unsubscribe?email=" + vppMember.getEmail());
+                emailUtils.sendMail(CaptchaActionEnum.CANCEL_LICENSE_ASSIGN.subject(), text, Collections.singletonList(vppMember.getEmail()));
+            });
+        }
     }
 
     @Override
@@ -610,4 +616,16 @@ public class VppLicenseCodeServiceImpl implements VppLicenseCodeService {
         // 解绑激活设备
         vppDeviceService.unBindByMemberId(null, Collections.singletonList(code.getCdkey()));
     }
+
+    @Override
+    public LicenseCodes getByMemberId(String id, String productCode) {
+        Products products = productService.getByCode(productCode);
+        LicenseCodesExample example = new LicenseCodesExample();
+        List<Integer> statuses = new ArrayList<>();
+        statuses.add(LicenseCodeStatusEnum.ASSIGNED.code());
+        statuses.add(LicenseCodeStatusEnum.PARTIALLY_ACTIVATED.code());
+        example.createCriteria().andMemberIdEqualTo(id).andProductIdEqualTo(products.getId()).andValidFlagIn(statuses);
+        List<LicenseCodes> list = licenseCodeMapper.selectByExample(example);
+        return CollectionUtils.isEmpty(list) ?  null: list.get(0) ;
+    }
 }

+ 9 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/impl/VppMemberServiceImpl.java

@@ -106,6 +106,15 @@ public class VppMemberServiceImpl implements VppMemberService {
         return CollectionUtils.isEmpty(users) ? null : users.get(0);
     }
 
+    @Override
+    public VppMember getByAccountSSO(String account) {
+        VppMemberExample example = new VppMemberExample();
+        example.createCriteria().andEmailEqualTo(account).andValidFlagEqualTo(ValidStatusEnum.VALID.value()).andIsSsoEqualTo(ValidStatusEnum.VALID.value());
+        List<VppMember> users = vppMemberMapper.selectByExample(example);
+        return CollectionUtils.isEmpty(users) ? null : users.get(0);
+    }
+
+
     @Override
     public VppMember create(VppMemberRegisterParam param) {
         //用户注册后都为普通用户,没有初始团队,团队将在申请试用后创建团队

+ 47 - 4
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/impl/VppRTeamMemberRoleServiceImpl.java

@@ -19,7 +19,9 @@ import cn.kdan.pdf.tech.core.utils.FileUtil;
 import cn.kdan.pdf.tech.core.utils.ThreadPoolSingleUtil;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
+import com.sun.jna.platform.win32.WinBase;
 import constant.CommonConstant;
+import enums.ValidStatusEnum;
 import exception.BackendRuntimeException;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang.StringUtils;
@@ -533,7 +535,7 @@ public class VppRTeamMemberRoleServiceImpl implements VppRTeamMemberRoleService
 
 
     @Override
-    public PageInfo<VppTeamMemberVO> pageForMember(Integer page, Integer pageSize, String teamId, String status, String productCode, String queryString) {
+    public PageInfo<VppTeamMemberVO> pageForMember(Integer page, Integer pageSize, String teamId, String status, String productCode, String queryString, String isSso) {
         List<String> teamIds = new ArrayList<>();
         VppMember member = vppMemberService.getCurrentUser();
         if(ObjectUtils.isEmpty(teamId)){
@@ -547,11 +549,11 @@ public class VppRTeamMemberRoleServiceImpl implements VppRTeamMemberRoleService
             throw new BackendRuntimeException(VppDeviceConstant.EXCEPTION_MSG_NO_TEAM);
         }
         PageHelper.startPage(page, pageSize);
-        return new PageInfo<>(vppRTeamMemberRoleMapper.listForMember(teamIds, member.getEmail(), queryString, status, productCode));
+        return new PageInfo<>(vppRTeamMemberRoleMapper.listForMember(teamIds, member.getEmail(), queryString, status, productCode, isSso));
     }
 
     @Override
-    public List<VppTeamMemberVO> listForMember(String teamId, String status, String productCode, String queryString) {
+    public List<VppTeamMemberVO> listForMember(String teamId, String status, String productCode, String queryString,String isSso) {
         VppMember member = vppMemberService.getCurrentUser();
         List<String> teamIds = new ArrayList<>();
         if(ObjectUtils.isEmpty(teamId)){
@@ -564,7 +566,7 @@ public class VppRTeamMemberRoleServiceImpl implements VppRTeamMemberRoleService
         if(CollectionUtils.isEmpty(teamIds)){
             throw new BackendRuntimeException(VppDeviceConstant.EXCEPTION_MSG_NO_TEAM);
         }
-        List<VppTeamMemberVO> vppTeamMemberVOS = vppRTeamMemberRoleMapper.listForMember(teamIds, member.getEmail(), queryString, status, productCode);
+        List<VppTeamMemberVO> vppTeamMemberVOS = vppRTeamMemberRoleMapper.listForMember(teamIds, member.getEmail(), queryString, status, productCode, isSso);
 
         for (VppTeamMemberVO vppTeamMemberVO : vppTeamMemberVOS) {
             if (StringUtils.isEmpty(vppTeamMemberVO.getProductNames())) {
@@ -614,5 +616,46 @@ public class VppRTeamMemberRoleServiceImpl implements VppRTeamMemberRoleService
         return vppRTeamMemberRoleMapper.selectByExample(example);
     }
 
+    @Override
+    public void removeSSOMembers(String memberId) {
+        List<VppRTeamMemberRole> vppRTeamMemberRoles = getVppRTeamMemberRoles(memberId);
+        List<String> ids = new ArrayList<>();
+        ids.add(vppRTeamMemberRoles.get(0).getTeamId());
+        //sso用户只有一个默认团队,只需要解绑设备序列码,并且修改用户数据
+        vppLicenseCodeService.unBindByMemberId(memberId, ids);
+        VppMember member = new VppMember();
+        member.setId(memberId);
+        member.setRole(RoleEnum.TEAM_MEMBER.code());
+        member.setValidFlag(ValidStatusEnum.INVALID.value());
+        vppMemberService.update(member);
+    }
+
+    @Override
+    public void revokeSSOMember(String memberId) {
+        VppMember member = new VppMember();
+        member.setId(memberId);
+        member.setRole(RoleEnum.TEAM_MEMBER.code());
+        member.setValidFlag(ValidStatusEnum.REVOKED.value());
+        vppMemberService.update(member);
+    }
+
+    @Override
+    public void reductionSSOMember(String memberId) {
+        VppMember member = new VppMember();
+        member.setId(memberId);
+        member.setRole(RoleEnum.TEAM_MEMBER.code());
+        member.setValidFlag(ValidStatusEnum.VALID.value());
+        vppMemberService.update(member);
+    }
+
+    @Override
+    public void accessSSOMember(String memberId) {
+        VppMember member = new VppMember();
+        member.setId(memberId);
+        member.setRole(RoleEnum.TEAM_MEMBER.code());
+        member.setValidFlag(ValidStatusEnum.VALID.value());
+        vppMemberService.update(member);
+    }
+
 
 }

+ 2 - 2
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/service/impl/VppTeamServiceImpl.java

@@ -244,9 +244,9 @@ public class VppTeamServiceImpl implements VppTeamService {
             sum = dto.getProductList().stream().mapToInt(CreateTeamDTO.Product::getLicenseNumber).sum();
         }
 
-
+       String teamId = ObjectUtils.isEmpty(dto.getTeamId())?CommonUtils.generateId():dto.getTeamId();
         // 新增团队
-        VppTeam newVppTeam = new VppTeam().withId(CommonUtils.generateId()).withValidFlag(ValidStatusEnum.VALID.value())
+        VppTeam newVppTeam = new VppTeam().withId(teamId).withValidFlag(ValidStatusEnum.VALID.value())
                 .withCompanyId(member.getCompanyId()).withCreateTime(new Date());
         newVppTeam.setName(dto.getTeamName());
         newVppTeam.setDescription(null != dto.getTeamDescription() ? dto.getTeamDescription() : StringUtils.EMPTY);

+ 109 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/utils/QuartzUtils.java

@@ -0,0 +1,109 @@
+package cn.kdan.pdf.tech.core.utils;
+
+import cn.kdan.pdf.tech.core.enums.ScheduleSettingTypeEnum;
+import cn.kdan.pdf.tech.core.model.ScheduleSetting;
+import lombok.extern.slf4j.Slf4j;
+import org.quartz.*;
+import org.quartz.impl.StdSchedulerFactory;
+import org.springframework.stereotype.Component;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import static org.quartz.CronScheduleBuilder.cronSchedule;
+import static org.quartz.JobBuilder.newJob;
+import static org.quartz.TriggerBuilder.newTrigger;
+
+@Slf4j
+@Component
+public class QuartzUtils {
+
+    private static Scheduler scheduler;
+
+    static {
+        try {
+            // 初始化调度器
+            scheduler = StdSchedulerFactory.getDefaultScheduler();
+            scheduler.start();
+        } catch (SchedulerException e) {
+            e.printStackTrace();
+        }
+    }
+
+
+    public static String generateCronExpression(String timeString) {
+        SimpleDateFormat sdfInput = new SimpleDateFormat("HH:mm");
+        Date time = null;
+        try {
+            time = sdfInput.parse(timeString);
+        } catch (ParseException e) {
+            throw new RuntimeException(e);
+        }
+        SimpleDateFormat sdfOutput = new SimpleDateFormat("ss mm HH * * ?");
+        String cronExpression = sdfOutput.format(time);
+
+        return cronExpression;
+    }
+
+    public static void scheduleJob(String jobName, String jobGroupName, Class<? extends Job> jobClass,
+                                   String triggerName, String triggerGroupName, String cronExpression, String directoryId) {
+        try {
+            // 创建定时任务
+            JobDetail job = newJob(jobClass)
+                    .withIdentity(jobName, jobGroupName)
+                    .build();
+
+            // 创建触发器
+            Trigger trigger = newTrigger()
+                    .withIdentity(triggerName, triggerGroupName)
+                    .withSchedule(cronSchedule(cronExpression))
+                    .build();
+            job.getJobDataMap().put("directoryId", directoryId);
+            // 关联定时任务和触发器
+            scheduler.scheduleJob(job, trigger);
+        } catch (Exception e) {
+            log.error("定时任务初始化失败", e);
+        }
+    }
+
+    public static void rescheduleJob(String triggerName, String triggerGroupName, String cronExpression, ScheduleSetting scheduleSetting) {
+        try {
+            if (scheduleSetting.getType().equals(ScheduleSettingTypeEnum.PER_HOUR.value())) {
+                cronExpression = "0 * * * *";
+            } else if (scheduleSetting.getType().equals(ScheduleSettingTypeEnum.SPECIFIED_TIME_EVERY_DAY.value())) {
+                cronExpression = generateCronExpression(scheduleSetting.getTime());
+            }
+            // 获取触发器键
+            TriggerKey triggerKey = new TriggerKey(triggerName, triggerGroupName);
+
+            // 创建新的触发器
+            Trigger newTrigger = newTrigger()
+                    .withIdentity(triggerKey)
+                    .withSchedule(cronSchedule(cronExpression))
+                    .build();
+
+            // 重新调度触发器
+            scheduler.rescheduleJob(triggerKey, newTrigger);
+        } catch (Exception e) {
+            log.error("定时任务重新调度失败", e);
+        }
+    }
+
+    public static void shutdownScheduler() throws SchedulerException {
+        scheduler.shutdown();
+    }
+
+    public static void deleteJob(String jobName, String groupName) {
+        try {
+            // 创建JobKey
+            JobKey jobKey = new JobKey(jobName, groupName);
+
+            // 删除任务
+            scheduler.deleteJob(jobKey);
+        } catch (Exception e) {
+            log.error("定时任务删除失败", e);
+        }
+    }
+
+}

+ 27 - 0
pdf-tech-core/src/main/java/cn/kdan/pdf/tech/core/utils/SyncJob.java

@@ -0,0 +1,27 @@
+package cn.kdan.pdf.tech.core.utils;
+
+import cn.kdan.pdf.tech.core.service.SyncService;
+import org.quartz.Job;
+import org.quartz.JobDataMap;
+import org.quartz.JobExecutionContext;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SyncJob implements Job, ApplicationContextAware {
+
+    private SyncService syncService;
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) {
+        syncService = applicationContext.getBean(SyncService.class);
+    }
+
+    @Override
+    public void execute(JobExecutionContext jobExecutionContext) {
+        JobDataMap dataMap = jobExecutionContext.getJobDetail().getJobDataMap();
+        String directoryId = dataMap.getString("directoryId");
+        syncService.startSync(directoryId);
+    }
+}

+ 2 - 2
pdf-tech-core/src/main/resources/generatorConfig.xml

@@ -35,7 +35,7 @@
                              targetPackage="cn.kdan.pdf.tech.core.mapper" targetProject="src/main/java">
             <property name="enableSubPackages" value="false"/>
         </javaClientGenerator>
-<!--        <table tableName="vpp_member"/>-->
+        <table tableName="vpp_member"/>
 <!--        <table tableName="oauth_client_details"/>-->
 <!--        <table tableName="subscriptions"/>-->
 <!--        <table tableName="products"/>-->
@@ -73,6 +73,6 @@
 <!--        <table tableName="directory"/>-->
 <!--        <table tableName="schedule_setting"/>-->
 <!--        <table tableName="domain"/>-->
-        <table tableName="directory_sync"/>
+<!--        <table tableName="directory_sync"/>-->
     </context>
 </generatorConfiguration>

+ 37 - 5
pdf-tech-core/src/main/resources/sqlmap/DirectoryMapper.xml

@@ -13,6 +13,8 @@
     <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
     <result column="valid_flag" jdbcType="VARCHAR" property="validFlag" />
     <result column="company_id" jdbcType="VARCHAR" property="companyId" />
+    <result column="team_id" jdbcType="VARCHAR" property="teamId" />
+    <result column="ms_group_ids" jdbcType="VARCHAR" property="msGroupIds" />
   </resultMap>
   <sql id="Example_Where_Clause">
     <where>
@@ -74,7 +76,7 @@
   </sql>
   <sql id="Base_Column_List">
     directory_id, `name`, client_secrets, `scope`, tenant_id, `type`, application_id, 
-    create_time, update_time, valid_flag, company_id
+    create_time, update_time, valid_flag, company_id, team_id, ms_group_ids
   </sql>
   <select id="selectByExample" parameterType="cn.kdan.pdf.tech.core.model.DirectoryExample" resultMap="BaseResultMap">
     select
@@ -110,11 +112,13 @@
     insert into directory (directory_id, `name`, client_secrets, 
       `scope`, tenant_id, `type`, 
       application_id, create_time, update_time, 
-      valid_flag, company_id)
+      valid_flag, company_id, team_id, 
+      ms_group_ids)
     values (#{directoryId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{clientSecrets,jdbcType=VARCHAR}, 
       #{scope,jdbcType=VARCHAR}, #{tenantId,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR}, 
       #{applicationId,jdbcType=VARCHAR}, #{createTime,jdbcType=TIMESTAMP}, #{updateTime,jdbcType=TIMESTAMP}, 
-      #{validFlag,jdbcType=VARCHAR}, #{companyId,jdbcType=VARCHAR})
+      #{validFlag,jdbcType=VARCHAR}, #{companyId,jdbcType=VARCHAR}, #{teamId,jdbcType=VARCHAR}, 
+      #{msGroupIds,jdbcType=VARCHAR})
   </insert>
   <insert id="insertSelective" parameterType="cn.kdan.pdf.tech.core.model.Directory">
     insert into directory
@@ -152,6 +156,12 @@
       <if test="companyId != null">
         company_id,
       </if>
+      <if test="teamId != null">
+        team_id,
+      </if>
+      <if test="msGroupIds != null">
+        ms_group_ids,
+      </if>
     </trim>
     <trim prefix="values (" suffix=")" suffixOverrides=",">
       <if test="directoryId != null">
@@ -187,6 +197,12 @@
       <if test="companyId != null">
         #{companyId,jdbcType=VARCHAR},
       </if>
+      <if test="teamId != null">
+        #{teamId,jdbcType=VARCHAR},
+      </if>
+      <if test="msGroupIds != null">
+        #{msGroupIds,jdbcType=VARCHAR},
+      </if>
     </trim>
   </insert>
   <select id="countByExample" parameterType="cn.kdan.pdf.tech.core.model.DirectoryExample" resultType="java.lang.Long">
@@ -231,6 +247,12 @@
       <if test="row.companyId != null">
         company_id = #{row.companyId,jdbcType=VARCHAR},
       </if>
+      <if test="row.teamId != null">
+        team_id = #{row.teamId,jdbcType=VARCHAR},
+      </if>
+      <if test="row.msGroupIds != null">
+        ms_group_ids = #{row.msGroupIds,jdbcType=VARCHAR},
+      </if>
     </set>
     <if test="example != null">
       <include refid="Update_By_Example_Where_Clause" />
@@ -248,7 +270,9 @@
       create_time = #{row.createTime,jdbcType=TIMESTAMP},
       update_time = #{row.updateTime,jdbcType=TIMESTAMP},
       valid_flag = #{row.validFlag,jdbcType=VARCHAR},
-      company_id = #{row.companyId,jdbcType=VARCHAR}
+      company_id = #{row.companyId,jdbcType=VARCHAR},
+      team_id = #{row.teamId,jdbcType=VARCHAR},
+      ms_group_ids = #{row.msGroupIds,jdbcType=VARCHAR}
     <if test="example != null">
       <include refid="Update_By_Example_Where_Clause" />
     </if>
@@ -286,6 +310,12 @@
       <if test="companyId != null">
         company_id = #{companyId,jdbcType=VARCHAR},
       </if>
+      <if test="teamId != null">
+        team_id = #{teamId,jdbcType=VARCHAR},
+      </if>
+      <if test="msGroupIds != null">
+        ms_group_ids = #{msGroupIds,jdbcType=VARCHAR},
+      </if>
     </set>
     where directory_id = #{directoryId,jdbcType=VARCHAR}
   </update>
@@ -300,7 +330,9 @@
       create_time = #{createTime,jdbcType=TIMESTAMP},
       update_time = #{updateTime,jdbcType=TIMESTAMP},
       valid_flag = #{validFlag,jdbcType=VARCHAR},
-      company_id = #{companyId,jdbcType=VARCHAR}
+      company_id = #{companyId,jdbcType=VARCHAR},
+      team_id = #{teamId,jdbcType=VARCHAR},
+      ms_group_ids = #{msGroupIds,jdbcType=VARCHAR}
     where directory_id = #{directoryId,jdbcType=VARCHAR}
   </update>
   <select id="selectByExampleWithRowbounds" parameterType="cn.kdan.pdf.tech.core.model.DirectoryExample" resultMap="BaseResultMap">

+ 41 - 26
pdf-tech-core/src/main/resources/sqlmap/VppMemberMapper.xml

@@ -21,6 +21,7 @@
     <result column="role" jdbcType="VARCHAR" property="role" />
     <result column="job" jdbcType="VARCHAR" property="job" />
     <result column="area" jdbcType="VARCHAR" property="area" />
+    <result column="is_sso" jdbcType="VARCHAR" property="isSso" />
   </resultMap>
   <sql id="Example_Where_Clause">
     <where>
@@ -81,9 +82,9 @@
     </where>
   </sql>
   <sql id="Base_Column_List">
-    id, email, full_name, subscriber_type, created_at, updated_at, subscribed, digest_password,
-    phone, valid_flag, industry, company_id, last_popularize_at, last_presented_coupon_at,
-    mailable, reset_token, role, job, area
+    id, email, full_name, subscriber_type, created_at, updated_at, subscribed, digest_password, 
+    phone, valid_flag, industry, company_id, last_popularize_at, last_presented_coupon_at, 
+    mailable, reset_token, `role`, job, area, is_sso
   </sql>
   <select id="selectByExample" parameterType="cn.kdan.pdf.tech.core.model.VppMemberExample" resultMap="BaseResultMap">
     select
@@ -100,7 +101,7 @@
     </if>
   </select>
   <select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="BaseResultMap">
-    select
+    select 
     <include refid="Base_Column_List" />
     from vpp_member
     where id = #{id,jdbcType=VARCHAR}
@@ -116,20 +117,20 @@
     </if>
   </delete>
   <insert id="insert" parameterType="cn.kdan.pdf.tech.core.model.VppMember">
-    insert into vpp_member (id, email, full_name,
-      subscriber_type, created_at, updated_at,
-      subscribed, digest_password, phone,
-      valid_flag, industry, company_id,
-      last_popularize_at, last_presented_coupon_at,
-      mailable, reset_token, role,
-      job, area)
-    values (#{id,jdbcType=VARCHAR}, #{email,jdbcType=VARCHAR}, #{fullName,jdbcType=VARCHAR},
-      #{subscriberType,jdbcType=INTEGER}, #{createdAt,jdbcType=TIMESTAMP}, #{updatedAt,jdbcType=TIMESTAMP},
-      #{subscribed,jdbcType=INTEGER}, #{digestPassword,jdbcType=VARCHAR}, #{phone,jdbcType=VARCHAR},
-      #{validFlag,jdbcType=VARCHAR}, #{industry,jdbcType=VARCHAR}, #{companyId,jdbcType=VARCHAR},
-      #{lastPopularizeAt,jdbcType=INTEGER}, #{lastPresentedCouponAt,jdbcType=TIMESTAMP},
-      #{mailable,jdbcType=INTEGER}, #{resetToken,jdbcType=INTEGER}, #{role,jdbcType=VARCHAR},
-      #{job,jdbcType=VARCHAR}, #{area,jdbcType=VARCHAR})
+    insert into vpp_member (id, email, full_name, 
+      subscriber_type, created_at, updated_at, 
+      subscribed, digest_password, phone, 
+      valid_flag, industry, company_id, 
+      last_popularize_at, last_presented_coupon_at, 
+      mailable, reset_token, `role`, 
+      job, area, is_sso)
+    values (#{id,jdbcType=VARCHAR}, #{email,jdbcType=VARCHAR}, #{fullName,jdbcType=VARCHAR}, 
+      #{subscriberType,jdbcType=INTEGER}, #{createdAt,jdbcType=TIMESTAMP}, #{updatedAt,jdbcType=TIMESTAMP}, 
+      #{subscribed,jdbcType=INTEGER}, #{digestPassword,jdbcType=VARCHAR}, #{phone,jdbcType=VARCHAR}, 
+      #{validFlag,jdbcType=VARCHAR}, #{industry,jdbcType=VARCHAR}, #{companyId,jdbcType=VARCHAR}, 
+      #{lastPopularizeAt,jdbcType=INTEGER}, #{lastPresentedCouponAt,jdbcType=TIMESTAMP}, 
+      #{mailable,jdbcType=INTEGER}, #{resetToken,jdbcType=INTEGER}, #{role,jdbcType=VARCHAR}, 
+      #{job,jdbcType=VARCHAR}, #{area,jdbcType=VARCHAR}, #{isSso,jdbcType=VARCHAR})
   </insert>
   <insert id="insertSelective" parameterType="cn.kdan.pdf.tech.core.model.VppMember">
     insert into vpp_member
@@ -183,7 +184,7 @@
         reset_token,
       </if>
       <if test="role != null">
-        role,
+        `role`,
       </if>
       <if test="job != null">
         job,
@@ -191,6 +192,9 @@
       <if test="area != null">
         area,
       </if>
+      <if test="isSso != null">
+        is_sso,
+      </if>
     </trim>
     <trim prefix="values (" suffix=")" suffixOverrides=",">
       <if test="id != null">
@@ -250,6 +254,9 @@
       <if test="area != null">
         #{area,jdbcType=VARCHAR},
       </if>
+      <if test="isSso != null">
+        #{isSso,jdbcType=VARCHAR},
+      </if>
     </trim>
   </insert>
   <select id="countByExample" parameterType="cn.kdan.pdf.tech.core.model.VppMemberExample" resultType="java.lang.Long">
@@ -310,7 +317,7 @@
         reset_token = #{row.resetToken,jdbcType=INTEGER},
       </if>
       <if test="row.role != null">
-        role = #{row.role,jdbcType=VARCHAR},
+        `role` = #{row.role,jdbcType=VARCHAR},
       </if>
       <if test="row.job != null">
         job = #{row.job,jdbcType=VARCHAR},
@@ -318,6 +325,9 @@
       <if test="row.area != null">
         area = #{row.area,jdbcType=VARCHAR},
       </if>
+      <if test="row.isSso != null">
+        is_sso = #{row.isSso,jdbcType=VARCHAR},
+      </if>
     </set>
     <if test="example != null">
       <include refid="Update_By_Example_Where_Clause" />
@@ -341,9 +351,10 @@
       last_presented_coupon_at = #{row.lastPresentedCouponAt,jdbcType=TIMESTAMP},
       mailable = #{row.mailable,jdbcType=INTEGER},
       reset_token = #{row.resetToken,jdbcType=INTEGER},
-      role = #{row.role,jdbcType=VARCHAR},
+      `role` = #{row.role,jdbcType=VARCHAR},
       job = #{row.job,jdbcType=VARCHAR},
-      area = #{row.area,jdbcType=VARCHAR}
+      area = #{row.area,jdbcType=VARCHAR},
+      is_sso = #{row.isSso,jdbcType=VARCHAR}
     <if test="example != null">
       <include refid="Update_By_Example_Where_Clause" />
     </if>
@@ -397,7 +408,7 @@
         reset_token = #{resetToken,jdbcType=INTEGER},
       </if>
       <if test="role != null">
-        role = #{role,jdbcType=VARCHAR},
+        `role` = #{role,jdbcType=VARCHAR},
       </if>
       <if test="job != null">
         job = #{job,jdbcType=VARCHAR},
@@ -405,6 +416,9 @@
       <if test="area != null">
         area = #{area,jdbcType=VARCHAR},
       </if>
+      <if test="isSso != null">
+        is_sso = #{isSso,jdbcType=VARCHAR},
+      </if>
     </set>
     where id = #{id,jdbcType=VARCHAR}
   </update>
@@ -425,9 +439,10 @@
       last_presented_coupon_at = #{lastPresentedCouponAt,jdbcType=TIMESTAMP},
       mailable = #{mailable,jdbcType=INTEGER},
       reset_token = #{resetToken,jdbcType=INTEGER},
-      role = #{role,jdbcType=VARCHAR},
+      `role` = #{role,jdbcType=VARCHAR},
       job = #{job,jdbcType=VARCHAR},
-      area = #{area,jdbcType=VARCHAR}
+      area = #{area,jdbcType=VARCHAR},
+      is_sso = #{isSso,jdbcType=VARCHAR}
     where id = #{id,jdbcType=VARCHAR}
   </update>
   <select id="selectByExampleWithRowbounds" parameterType="cn.kdan.pdf.tech.core.model.VppMemberExample" resultMap="BaseResultMap">
@@ -444,4 +459,4 @@
       order by ${orderByClause}
     </if>
   </select>
-</mapper>
+</mapper>

+ 12 - 4
pdf-tech-core/src/main/resources/sqlmap/ext/ExtVppRTeamMemberRoleMapper.xml

@@ -77,14 +77,16 @@
     <result column="created_at" jdbcType="VARCHAR" property="createdAt" />
     <result column="valid_flag" jdbcType="VARCHAR" property="validFlag" />
     <result column="team_name" jdbcType="VARCHAR" property="teamName" />
+    <result column="is_sso" jdbcType="INTEGER" property="isSso" />
+    <result column="updated_at" jdbcType="VARCHAR" property="updatedAt" />
   </resultMap>
 
   <select id="listForMember" resultMap="MemberListResultMap">
-    select a.full_name,a.email,a.id,a.created_at,a.valid_flag,a.team_name,
+    select a.full_name,a.email,a.id,a.created_at,a.updated_at,a.valid_flag,a.team_name,
     string_agg(a.product_name, ',') product_names,
     string_agg(a.code, ',') codes
     from (
-    select vm.full_name,vm.email,vm.id,vm.created_at,vm.valid_flag ,vt.name team_name,p.name product_name, p.code
+    select vm.full_name,vm.email,vm.id,vm.created_at,vm.updated_at,vm.valid_flag ,vt.name team_name,p.name product_name, p.code
     from vpp_r_team_member_role vrtmr
     left join vpp_team vt on vrtmr.team_id = vt.id
     left join vpp_member vm on vrtmr.member_id = vm.id
@@ -106,9 +108,15 @@
     <if test="status != null and status != ''">
       and vm.valid_flag = #{status}
     </if>
-    group by vm.full_name, vm.email, vm.id, vm.created_at, vt.name, vm.valid_flag, p.name, p.code
+    <if test="isSso != null and isSso != ''">
+      and vm.is_sso = #{isSso}
+      <if test="status = null and status = ''">
+        and vm.valid_flag != '0'
+      </if>
+    </if>
+    group by vm.full_name, vm.email, vm.id, vm.created_at, vm.updated_at, vt.name, vm.valid_flag, p.name, p.code
     order by vm.created_at desc
-    ) as a   group by a.full_name,a.email,a.id,a.created_at,a.valid_flag,a.team_name
+    ) as a   group by a.full_name,a.email,a.id,a.created_at,a.updated_at,a.valid_flag,a.team_name
 
   </select>