diff --git a/maxkey-common/src/main/java/org/maxkey/util/JdbcUtils.java b/maxkey-common/src/main/java/org/maxkey/util/JdbcUtils.java new file mode 100644 index 000000000..7b2f7d920 --- /dev/null +++ b/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"); + } + } + } + + +} diff --git a/maxkey-persistence/src/main/java/org/maxkey/persistence/service/AccountsService.java b/maxkey-persistence/src/main/java/org/maxkey/persistence/service/AccountsService.java index 7a8971166..0e4b2be08 100644 --- a/maxkey-persistence/src/main/java/org/maxkey/persistence/service/AccountsService.java +++ b/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{ @Autowired - ProvisionService mqPersistService; + ProvisionService provisionService; @Autowired UserInfoService userInfoService; @@ -71,14 +71,14 @@ public class AccountsService extends JpaBaseService{ 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{ 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 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); diff --git a/maxkey-persistence/src/main/java/org/maxkey/persistence/service/OrganizationsService.java b/maxkey-persistence/src/main/java/org/maxkey/persistence/service/OrganizationsService.java index ba72f7d42..9f3fd5121 100644 --- a/maxkey-persistence/src/main/java/org/maxkey/persistence/service/OrganizationsService.java +++ b/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{ @Autowired - ProvisionService messageQueueService; + ProvisionService provisionService; public OrganizationsService() { super(OrganizationsMapper.class); @@ -51,7 +51,7 @@ public class OrganizationsService extends JpaBaseService{ 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{ 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{ public boolean delete(Organizations organization) { if(super.delete(organization)){ - messageQueueService.send( + provisionService.send( ProvisionTopic.ORG_TOPIC, organization, ProvisionAction.DELETE_ACTION); return true; } diff --git a/maxkey-persistence/src/main/java/org/maxkey/persistence/service/UserInfoService.java b/maxkey-persistence/src/main/java/org/maxkey/persistence/service/UserInfoService.java index 6aaf531f3..8618a7fa8 100644 --- a/maxkey-persistence/src/main/java/org/maxkey/persistence/service/UserInfoService.java +++ b/maxkey-persistence/src/main/java/org/maxkey/persistence/service/UserInfoService.java @@ -56,7 +56,7 @@ public class UserInfoService extends JpaBaseService { PasswordPolicyValidator passwordPolicyValidator; @Autowired - ProvisionService messageQueueService; + ProvisionService provisionService; AccountsService accountsService; @@ -75,9 +75,28 @@ public class UserInfoService extends JpaBaseService { 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 { 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 { 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 { 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); diff --git a/maxkey-synchronizers/maxkey-synchronizer-jdbc/build.gradle b/maxkey-synchronizers/maxkey-synchronizer-jdbc/build.gradle new file mode 100644 index 000000000..98d8a507b --- /dev/null +++ b/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") + +} \ No newline at end of file diff --git a/maxkey-synchronizers/maxkey-synchronizer-jdbc/src/main/java/org/maxkey/synchronizer/jdbc/JdbcOrganizationService.java b/maxkey-synchronizers/maxkey-synchronizer-jdbc/src/main/java/org/maxkey/synchronizer/jdbc/JdbcOrganizationService.java new file mode 100644 index 000000000..6e9f3c647 --- /dev/null +++ b/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; + } +} diff --git a/maxkey-synchronizers/maxkey-synchronizer-jdbc/src/main/java/org/maxkey/synchronizer/jdbc/JdbcSynchronizerService.java b/maxkey-synchronizers/maxkey-synchronizer-jdbc/src/main/java/org/maxkey/synchronizer/jdbc/JdbcSynchronizerService.java new file mode 100644 index 000000000..b94f42532 --- /dev/null +++ b/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; + } + + + +} diff --git a/maxkey-synchronizers/maxkey-synchronizer-jdbc/src/main/java/org/maxkey/synchronizer/jdbc/JdbcUsersService.java b/maxkey-synchronizers/maxkey-synchronizer-jdbc/src/main/java/org/maxkey/synchronizer/jdbc/JdbcUsersService.java new file mode 100644 index 000000000..35c2f37a5 --- /dev/null +++ b/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; + } + +} diff --git a/maxkey-webs/maxkey-web-mgt/build.gradle b/maxkey-webs/maxkey-web-mgt/build.gradle index 3f9bf2316..fd30a4ad1 100644 --- a/maxkey-webs/maxkey-web-mgt/build.gradle +++ b/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") diff --git a/maxkey-webs/maxkey-web-mgt/config/build_docker.gradle b/maxkey-webs/maxkey-web-mgt/config/build_docker.gradle index 300d2ce65..37dd7366a 100644 --- a/maxkey-webs/maxkey-web-mgt/config/build_docker.gradle +++ b/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") diff --git a/maxkey-webs/maxkey-web-mgt/config/build_jar.gradle b/maxkey-webs/maxkey-web-mgt/config/build_jar.gradle index 8469fd1e3..721b6a21c 100644 --- a/maxkey-webs/maxkey-web-mgt/config/build_jar.gradle +++ b/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") diff --git a/maxkey-webs/maxkey-web-mgt/config/build_standard.gradle b/maxkey-webs/maxkey-web-mgt/config/build_standard.gradle index 937cd58c9..5cbc6cd60 100644 --- a/maxkey-webs/maxkey-web-mgt/config/build_standard.gradle +++ b/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") diff --git a/settings.gradle b/settings.gradle index b9a54d1d7..5fc48c056 100644 --- a/settings.gradle +++ b/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',