MaxKey 2 rokov pred
rodič
commit
31ebb5c85a

+ 111 - 0
maxkey-common/src/main/java/org/maxkey/util/JdbcUtils.java

@@ -0,0 +1,111 @@
+/*
+ * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+
+package org.maxkey.util;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+public class JdbcUtils {
+
+	public static Connection connect(String url, String user, String pwd, String driverClass) {
+		Connection conn = null;
+		try {
+			Class.forName(driverClass);
+			conn = java.sql.DriverManager.getConnection(url, user, pwd);
+			return conn;
+		} catch (ClassNotFoundException e) {
+			System.out.println("ClassNotFoundException");
+			return null;
+		} catch (SQLException e) {
+			System.out.println("SQLException");
+		}
+		return null;
+	}
+
+	public void release(Connection conn) {
+		if (conn != null) {
+			try {
+				conn.close();
+			} catch (SQLException e) {
+				System.out.println("SQLException");
+			}
+		}
+	}
+
+	public static void release(Connection conn, Statement stmt, ResultSet rs) {
+		if (rs != null)
+			try {
+				rs.close();
+				rs = null;
+			} catch (SQLException e) {
+				System.out.println("SQLException");
+			}
+		if (stmt != null)
+			try {
+				stmt.close();
+				stmt = null;
+			} catch (SQLException e) {
+				System.out.println("SQLException");
+			}
+		if (conn != null) {
+			try {
+				conn.close();
+				conn = null;
+			} catch (SQLException e) {
+				System.out.println("SQLException");
+			}
+		}
+	}
+	
+	public static void release(Connection conn, Statement stmt, PreparedStatement pstmt, ResultSet rs) {
+		if (rs != null)
+			try {
+				rs.close();
+				rs = null;
+			} catch (SQLException e) {
+				System.out.println("ResultSet Close Exception");
+			}
+		if (stmt != null)
+			try {
+				stmt.close();
+				stmt = null;
+			} catch (SQLException e) {
+				System.out.println("Statement Close Exception");
+			}
+		if (pstmt != null)
+			try {
+				pstmt.close();
+				pstmt = null;
+			} catch (SQLException e) {
+				System.out.println("PreparedStatement Close Exception");
+			}
+		if (conn != null) {
+			try {
+				conn.close();
+				conn = null;
+			} catch (SQLException e) {
+				System.out.println("Connection Close Exception");
+			}
+		}
+	}
+
+	
+}

+ 7 - 7
maxkey-persistence/src/main/java/org/maxkey/persistence/service/AccountsService.java

@@ -45,7 +45,7 @@ import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombi
 public class AccountsService  extends JpaBaseService<Accounts>{
 
     @Autowired
-    ProvisionService mqPersistService;
+    ProvisionService provisionService;
     
     @Autowired
     UserInfoService  userInfoService;
@@ -71,14 +71,14 @@ public class AccountsService  extends JpaBaseService<Accounts>{
 	
 	 public boolean insert(Accounts account) {
 	     if (super.insert(account)) {
-	            if(mqPersistService.getApplicationConfig().isProvisionSupport()) {
+	            if(provisionService.getApplicationConfig().isProvisionSupport()) {
 	                UserInfo loadUserInfo = userInfoService.findUserRelated(account.getUserId());
 	                account.setUserInfo(loadUserInfo);
 	                OrganizationsCast cast = new OrganizationsCast();
                     cast.setProvider(account.getAppId());
                     cast.setOrgId(loadUserInfo.getDepartmentId());
                     account.setOrgCast(organizationsCastService.query(cast));
-                    mqPersistService.send(
+                    provisionService.send(
 	                        ProvisionTopic.ACCOUNT_TOPIC, 
 	                        account,
 	                        ProvisionAction.CREATE_ACTION);
@@ -91,14 +91,14 @@ public class AccountsService  extends JpaBaseService<Accounts>{
 	 
    public boolean update(Accounts account) {
          if (super.update(account)) {
-        	 if(mqPersistService.getApplicationConfig().isProvisionSupport()) {
+        	 if(provisionService.getApplicationConfig().isProvisionSupport()) {
                     UserInfo loadUserInfo = userInfoService.findUserRelated(account.getUserId());
                     account.setUserInfo(loadUserInfo);
                     OrganizationsCast cast = new OrganizationsCast();
                     cast.setProvider(account.getAppId());
                     cast.setOrgId(loadUserInfo.getDepartmentId());
                     account.setOrgCast(organizationsCastService.query(cast));
-                    mqPersistService.send(
+                    provisionService.send(
                             ProvisionTopic.ACCOUNT_TOPIC, 
                             account,
                             ProvisionAction.UPDATE_ACTION);
@@ -116,10 +116,10 @@ public class AccountsService  extends JpaBaseService<Accounts>{
        Accounts account = this.get(id);
        if (super.remove(id)) {
               UserInfo loadUserInfo = null;
-              if(mqPersistService.getApplicationConfig().isProvisionSupport()) {
+              if(provisionService.getApplicationConfig().isProvisionSupport()) {
                   loadUserInfo = userInfoService.findUserRelated(account.getUserId());
                   account.setUserInfo(loadUserInfo);
-                  mqPersistService.send(
+                  provisionService.send(
                           ProvisionTopic.ACCOUNT_TOPIC, 
                           account,
                           ProvisionAction.DELETE_ACTION);

+ 4 - 4
maxkey-persistence/src/main/java/org/maxkey/persistence/service/OrganizationsService.java

@@ -35,7 +35,7 @@ import org.springframework.stereotype.Repository;
 public class OrganizationsService  extends JpaBaseService<Organizations>{
 
     @Autowired
-    ProvisionService messageQueueService;
+    ProvisionService provisionService;
     
 	public OrganizationsService() {
 		super(OrganizationsMapper.class);
@@ -51,7 +51,7 @@ public class OrganizationsService  extends JpaBaseService<Organizations>{
 	
 	 public boolean insert(Organizations organization) {
 	     if(super.insert(organization)){
-	    	 messageQueueService.send(
+	    	 provisionService.send(
                      ProvisionTopic.ORG_TOPIC, organization, ProvisionAction.CREATE_ACTION);
              return true;
          }
@@ -60,7 +60,7 @@ public class OrganizationsService  extends JpaBaseService<Organizations>{
 	 
 	 public boolean update(Organizations organization) {
 	     if(super.update(organization)){
-	    	 messageQueueService.send(
+	    	 provisionService.send(
                      ProvisionTopic.ORG_TOPIC, organization, ProvisionAction.UPDATE_ACTION);
              return true;
          }
@@ -84,7 +84,7 @@ public class OrganizationsService  extends JpaBaseService<Organizations>{
 	 
 	 public boolean delete(Organizations organization) {
 	     if(super.delete(organization)){
-	    	 messageQueueService.send(
+	    	 provisionService.send(
                      ProvisionTopic.ORG_TOPIC, organization, ProvisionAction.DELETE_ACTION);
              return true;
          }

+ 27 - 8
maxkey-persistence/src/main/java/org/maxkey/persistence/service/UserInfoService.java

@@ -56,7 +56,7 @@ public class UserInfoService extends JpaBaseService<UserInfo> {
 	PasswordPolicyValidator passwordPolicyValidator;
 	
 	@Autowired
-	ProvisionService messageQueueService;
+	ProvisionService provisionService;
 
 	AccountsService accountsService;
 	
@@ -75,9 +75,28 @@ public class UserInfoService extends JpaBaseService<UserInfo> {
     public boolean insert(UserInfo userInfo) {
     	this.passwordEncoder(userInfo);
         if (super.insert(userInfo)) {
-        	if(messageQueueService.getApplicationConfig().isProvisionSupport()) {
+        	if(provisionService.getApplicationConfig().isProvisionSupport()) {
                 UserInfo loadUserInfo = findUserRelated(userInfo.getId());
-                messageQueueService.send(
+                provisionService.send(
+                        ProvisionTopic.USERINFO_TOPIC, 
+                        loadUserInfo,
+                        ProvisionAction.CREATE_ACTION);
+            }
+            
+            return true;
+        }
+
+        return false;
+    }
+    
+    public boolean insert(UserInfo userInfo,boolean passwordEncoder) {
+    	if(passwordEncoder) {
+    		this.passwordEncoder(userInfo);
+    	}
+        if (super.insert(userInfo)) {
+        	if(provisionService.getApplicationConfig().isProvisionSupport()) {
+                UserInfo loadUserInfo = findUserRelated(userInfo.getId());
+                provisionService.send(
                         ProvisionTopic.USERINFO_TOPIC, 
                         loadUserInfo,
                         ProvisionAction.CREATE_ACTION);
@@ -92,10 +111,10 @@ public class UserInfoService extends JpaBaseService<UserInfo> {
     public boolean update(UserInfo userInfo) {
     	ChangePassword changePassword = this.passwordEncoder(userInfo);
         if (super.update(userInfo)) {
-        	if(messageQueueService.getApplicationConfig().isProvisionSupport()) {
+        	if(provisionService.getApplicationConfig().isProvisionSupport()) {
                 UserInfo loadUserInfo = findUserRelated(userInfo.getId());
                 accountUpdate(loadUserInfo);
-                messageQueueService.send(
+                provisionService.send(
                         ProvisionTopic.USERINFO_TOPIC, 
                         loadUserInfo,
                         ProvisionAction.UPDATE_ACTION);
@@ -110,12 +129,12 @@ public class UserInfoService extends JpaBaseService<UserInfo> {
 	
 	public boolean delete(UserInfo userInfo) {
 	    UserInfo loadUserInfo = null;
-	    if(messageQueueService.getApplicationConfig().isProvisionSupport()) {
+	    if(provisionService.getApplicationConfig().isProvisionSupport()) {
 	        loadUserInfo = findUserRelated(userInfo.getId());
 	    }
 	    
 		if( super.delete(userInfo)){
-			messageQueueService.send(
+			provisionService.send(
 		            ProvisionTopic.USERINFO_TOPIC, 
 		            loadUserInfo, 
 		            ProvisionAction.DELETE_ACTION);
@@ -313,7 +332,7 @@ public class UserInfoService extends JpaBaseService<UserInfo> {
 	    if(changePassworded !=null && StringUtils.isNotBlank(changePassworded.getPassword())) {
 	    	UserInfo loadUserInfo = findByUsername(changePassworded.getUsername());
     	    ChangePassword changePassword = new ChangePassword(loadUserInfo);
-    	    messageQueueService.send(
+    	    provisionService.send(
                     ProvisionTopic.PASSWORD_TOPIC, 
                     changePassword, 
                     ProvisionAction.PASSWORD_ACTION);

+ 14 - 0
maxkey-synchronizers/maxkey-synchronizer-jdbc/build.gradle

@@ -0,0 +1,14 @@
+description = "maxkey-synchronizer-jdbc"
+
+apply plugin: 'java'
+
+dependencies {
+	//local jars
+	implementation fileTree(dir: '../maxkey-lib/*/', include: '*.jar')
+	
+	implementation project(":maxkey-common")
+	implementation project(":maxkey-core")
+	implementation project(":maxkey-persistence")
+	implementation project(":maxkey-synchronizers:maxkey-synchronizer")
+   
+}

+ 85 - 0
maxkey-synchronizers/maxkey-synchronizer-jdbc/src/main/java/org/maxkey/synchronizer/jdbc/JdbcOrganizationService.java

@@ -0,0 +1,85 @@
+/*
+ * Copyright [2021] [MaxKey of copyright http://www.maxkey.top]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+
+package org.maxkey.synchronizer.jdbc;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import org.maxkey.constants.ConstsStatus;
+import org.maxkey.entity.Organizations;
+import org.maxkey.synchronizer.AbstractSynchronizerService;
+import org.maxkey.synchronizer.ISynchronizerService;
+import org.maxkey.util.JdbcUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+@Service
+public class JdbcOrganizationService  extends AbstractSynchronizerService  implements ISynchronizerService{
+	final static Logger _logger = LoggerFactory.getLogger(JdbcOrganizationService.class);
+
+	 Connection conn = null;
+     Statement  stmt = null;
+     ResultSet  rs 	 = null;
+	
+     String querySql = "select * from org";
+	
+	public void sync() {
+		try {
+			conn = JdbcUtils.connect(
+					synchronizer.getProviderUrl(), 
+					synchronizer.getPrincipal(), 
+					synchronizer.getCredentials(), 
+					synchronizer.getDriverClass());
+			
+			stmt = conn.createStatement();
+			rs = stmt.executeQuery(querySql);
+			while(rs.next()) {
+				Organizations queryOrg = this.organizationsService.get(rs.getString("id"));
+				if(queryOrg == null) {
+					Organizations org = buildOrganization(rs);
+					organizationsService.insert(org);
+				}else{
+					//this.organizationsService.update(org);
+				}
+			}
+			JdbcUtils.release(conn, stmt, rs);
+		} catch (Exception e) {
+			_logger.error("Exception " , e);
+		}
+	}
+	
+	
+	public Organizations buildOrganization(ResultSet  rs) {
+		try {
+		    Organizations org = new Organizations();
+		
+			org.setId(org.generateId());
+			org.setOrgCode(rs.getString("code"));
+			org.setOrgName(rs.getString("orgname"));
+			org.setInstId(this.synchronizer.getInstId());
+			org.setStatus(ConstsStatus.ACTIVE);
+			
+			_logger.debug("Organization " + org);
+			return org;
+		} catch (Exception e) {
+			_logger.error("NamingException " , e);
+		}
+		return null;
+	}
+}

+ 68 - 0
maxkey-synchronizers/maxkey-synchronizer-jdbc/src/main/java/org/maxkey/synchronizer/jdbc/JdbcSynchronizerService.java

@@ -0,0 +1,68 @@
+/*
+ * Copyright [2021] [MaxKey of copyright http://www.maxkey.top]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+
+package org.maxkey.synchronizer.jdbc;
+
+import org.maxkey.entity.Synchronizers;
+import org.maxkey.synchronizer.ISynchronizerService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class JdbcSynchronizerService   implements ISynchronizerService{
+	final static Logger _logger = LoggerFactory.getLogger(JdbcSynchronizerService.class);
+	
+	Synchronizers synchronizer;
+	
+	@Autowired
+	JdbcUsersService jdbcUsersService;
+	
+	@Autowired
+	JdbcOrganizationService jdbcOrganizationService;
+	
+	public JdbcSynchronizerService() {
+		super();
+	}
+
+	public void sync() {
+		_logger.info("Sync ...");
+		jdbcOrganizationService.setSynchronizer(synchronizer);
+		jdbcOrganizationService.sync();
+		
+		jdbcUsersService.setSynchronizer(synchronizer);
+		jdbcUsersService.sync();
+		
+	}
+
+	public void setJdbcUsersService(JdbcUsersService jdbcUsersService) {
+		this.jdbcUsersService = jdbcUsersService;
+	}
+
+	public void setJdbcOrganizationService(JdbcOrganizationService jdbcOrganizationService) {
+		this.jdbcOrganizationService = jdbcOrganizationService;
+	}
+
+	@Override
+	public void setSynchronizer(Synchronizers synchronizer) {
+		this.synchronizer = synchronizer;
+	}
+
+
+	
+}

+ 97 - 0
maxkey-synchronizers/maxkey-synchronizer-jdbc/src/main/java/org/maxkey/synchronizer/jdbc/JdbcUsersService.java

@@ -0,0 +1,97 @@
+/*
+ * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+
+package org.maxkey.synchronizer.jdbc;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.maxkey.constants.ConstsStatus;
+import org.maxkey.entity.UserInfo;
+import org.maxkey.synchronizer.AbstractSynchronizerService;
+import org.maxkey.synchronizer.ISynchronizerService;
+import org.maxkey.util.JdbcUtils;
+import org.maxkey.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+@Service
+public class JdbcUsersService extends AbstractSynchronizerService    implements ISynchronizerService{
+	final static Logger _logger = LoggerFactory.getLogger(JdbcUsersService.class);
+
+	 Connection conn = null;
+     Statement  stmt = null;
+     ResultSet  rs 	 = null;
+	
+     String querySql = "select * from account";
+	public void sync() {
+		_logger.info("Sync Jdbc Users...");
+		try {
+			conn = JdbcUtils.connect(
+					synchronizer.getProviderUrl(), 
+					synchronizer.getPrincipal(), 
+					synchronizer.getCredentials(), 
+					synchronizer.getDriverClass());
+			
+			stmt = conn.createStatement();
+			rs = stmt.executeQuery(querySql);
+			long insertCount = 0;
+			long updateCount = 0;
+			long readCount 	 = 0;
+			while(rs.next()) {
+				UserInfo queryUser = this.userInfoService.findByUsername(rs.getString("mobile"));
+				readCount ++;
+				if(queryUser == null) {
+					UserInfo user = buildUserInfo(rs);
+					if(StringUtils.isBlank(rs.getString("password"))) {
+						user.setPassword(rs.getString("mobile"));
+						userInfoService.insert(user,true);
+					}else {
+						user.setPassword("{bcrypt}"+rs.getString("password"));
+						userInfoService.insert(user,false);
+					}
+					insertCount++;
+				}else{
+					//userInfoService.update(queryUser);
+					updateCount++;
+				}
+				_logger.debug("read Count {} , insert Count {} , updateCount {} " , readCount,insertCount,updateCount);
+			}
+			_logger.info("read Count {} , insert Count {} , updateCount {} " , readCount,insertCount,updateCount);
+			JdbcUtils.release(conn, stmt, rs);
+		} catch (Exception e) {
+			_logger.error("Exception " , e);
+		}
+	}
+	
+	public UserInfo buildUserInfo(ResultSet  rs) throws SQLException {
+		UserInfo user = new UserInfo();
+		user.setId(rs.getString("id"));
+		user.setUsername(rs.getString("mobile"));
+		user.setDisplayName(rs.getString("nickname"));
+		user.setNickName(rs.getString("nickname"));
+		user.setMobile(rs.getString("mobile"));
+		user.setEmail(rs.getString("email"));
+		user.setInstId(this.synchronizer.getInstId());
+		user.setStatus(ConstsStatus.ACTIVE);
+		return user;
+	}
+
+}

+ 1 - 0
maxkey-webs/maxkey-web-mgt/build.gradle

@@ -24,6 +24,7 @@ dependencies {
    	implementation project(":maxkey-synchronizers:maxkey-synchronizer")
    	implementation project(":maxkey-synchronizers:maxkey-synchronizer-activedirectory")
    	implementation project(":maxkey-synchronizers:maxkey-synchronizer-feishu")
+   	implementation project(":maxkey-synchronizers:maxkey-synchronizer-jdbc")
    	implementation project(":maxkey-synchronizers:maxkey-synchronizer-ldap")
    	implementation project(":maxkey-synchronizers:maxkey-synchronizer-workweixin")
    	implementation project(":maxkey-synchronizers:maxkey-synchronizer-dingtalk")

+ 1 - 0
maxkey-webs/maxkey-web-mgt/config/build_docker.gradle

@@ -59,6 +59,7 @@ dependencies {
    	implementation project(":maxkey-synchronizers:maxkey-synchronizer")
    	implementation project(":maxkey-synchronizers:maxkey-synchronizer-activedirectory")
    	implementation project(":maxkey-synchronizers:maxkey-synchronizer-feishu")
+   	implementation project(":maxkey-synchronizers:maxkey-synchronizer-jdbc")
    	implementation project(":maxkey-synchronizers:maxkey-synchronizer-ldap")
    	implementation project(":maxkey-synchronizers:maxkey-synchronizer-workweixin")
    	implementation project(":maxkey-synchronizers:maxkey-synchronizer-dingtalk")

+ 1 - 0
maxkey-webs/maxkey-web-mgt/config/build_jar.gradle

@@ -60,6 +60,7 @@ dependencies {
    	implementation project(":maxkey-synchronizers:maxkey-synchronizer")
    	implementation project(":maxkey-synchronizers:maxkey-synchronizer-activedirectory")
    	implementation project(":maxkey-synchronizers:maxkey-synchronizer-feishu")
+   	implementation project(":maxkey-synchronizers:maxkey-synchronizer-jdbc")
    	implementation project(":maxkey-synchronizers:maxkey-synchronizer-ldap")
    	implementation project(":maxkey-synchronizers:maxkey-synchronizer-workweixin")
    	implementation project(":maxkey-synchronizers:maxkey-synchronizer-dingtalk")

+ 1 - 0
maxkey-webs/maxkey-web-mgt/config/build_standard.gradle

@@ -24,6 +24,7 @@ dependencies {
    	implementation project(":maxkey-synchronizers:maxkey-synchronizer")
    	implementation project(":maxkey-synchronizers:maxkey-synchronizer-activedirectory")
    	implementation project(":maxkey-synchronizers:maxkey-synchronizer-feishu")
+   	implementation project(":maxkey-synchronizers:maxkey-synchronizer-jdbc")
    	implementation project(":maxkey-synchronizers:maxkey-synchronizer-ldap")
    	implementation project(":maxkey-synchronizers:maxkey-synchronizer-workweixin")
    	implementation project(":maxkey-synchronizers:maxkey-synchronizer-dingtalk")

+ 1 - 0
settings.gradle

@@ -39,6 +39,7 @@ include (
 	'maxkey-synchronizers:maxkey-synchronizer-reorgdept',
 	'maxkey-synchronizers:maxkey-synchronizer-activedirectory',
 	'maxkey-synchronizers:maxkey-synchronizer-feishu',
+	'maxkey-synchronizers:maxkey-synchronizer-jdbc',
 	'maxkey-synchronizers:maxkey-synchronizer-ldap',
 	'maxkey-synchronizers:maxkey-synchronizer-dingtalk',
 	'maxkey-synchronizers:maxkey-synchronizer-workweixin',