Просмотр исходного кода

Identity Provisioning based on Kafka

Identity Provisioning based on Kafka, Have many connectors
shimingxy 5 лет назад
Родитель
Сommit
0ae9bcda77
87 измененных файлов с 2611 добавлено и 11 удалено
  1. 1 1
      .checkstyle
  2. 15 2
      build.gradle
  3. 6 0
      maxkey-connectors/.classpath
  4. 28 0
      maxkey-connectors/.project
  5. 36 0
      maxkey-connectors/maxkey-connector-activedirectory/.classpath
  6. 41 0
      maxkey-connectors/maxkey-connector-activedirectory/.project
  7. 2 0
      maxkey-connectors/maxkey-connector-activedirectory/.settings/org.eclipse.buildship.core.prefs
  8. 2 0
      maxkey-connectors/maxkey-connector-activedirectory/.settings/org.eclipse.core.resources.prefs
  9. 14 0
      maxkey-connectors/maxkey-connector-activedirectory/.settings/org.eclipse.jdt.core.prefs
  10. 3 0
      maxkey-connectors/maxkey-connector-activedirectory/.settings/org.eclipse.jdt.launching.prefs
  11. 22 0
      maxkey-connectors/maxkey-connector-activedirectory/.settings/org.eclipse.wst.common.component
  12. 6 0
      maxkey-connectors/maxkey-connector-activedirectory/.settings/org.eclipse.wst.common.project.facet.core.xml
  13. 2 0
      maxkey-connectors/maxkey-connector-activedirectory/.settings/org.springframework.ide.eclipse.prefs
  14. 17 0
      maxkey-connectors/maxkey-connector-activedirectory/build.gradle
  15. 56 0
      maxkey-connectors/maxkey-connector-activedirectory/src/main/java/org/maxkey/connector/ActivedirectoryConsumerApplication.java
  16. 181 0
      maxkey-connectors/maxkey-connector-activedirectory/src/main/java/org/maxkey/connector/activedirectory/Group2Activedirectory.java
  17. 124 0
      maxkey-connectors/maxkey-connector-activedirectory/src/main/java/org/maxkey/connector/activedirectory/Organization2Activedirectory.java
  18. 86 0
      maxkey-connectors/maxkey-connector-activedirectory/src/main/java/org/maxkey/connector/activedirectory/Password2Activedirectory.java
  19. 271 0
      maxkey-connectors/maxkey-connector-activedirectory/src/main/java/org/maxkey/connector/activedirectory/UserInfo2Activedirectory.java
  20. 48 0
      maxkey-connectors/maxkey-connector-activedirectory/src/main/resources/application.properties
  21. 36 0
      maxkey-connectors/maxkey-connector-base/.classpath
  22. 41 0
      maxkey-connectors/maxkey-connector-base/.project
  23. 2 0
      maxkey-connectors/maxkey-connector-base/.settings/org.eclipse.buildship.core.prefs
  24. 2 0
      maxkey-connectors/maxkey-connector-base/.settings/org.eclipse.core.resources.prefs
  25. 14 0
      maxkey-connectors/maxkey-connector-base/.settings/org.eclipse.jdt.core.prefs
  26. 3 0
      maxkey-connectors/maxkey-connector-base/.settings/org.eclipse.jdt.launching.prefs
  27. 19 0
      maxkey-connectors/maxkey-connector-base/.settings/org.eclipse.wst.common.component
  28. 6 0
      maxkey-connectors/maxkey-connector-base/.settings/org.eclipse.wst.common.project.facet.core.xml
  29. 2 0
      maxkey-connectors/maxkey-connector-base/.settings/org.springframework.ide.eclipse.prefs
  30. 16 0
      maxkey-connectors/maxkey-connector-base/build.gradle
  31. 53 0
      maxkey-connectors/maxkey-connector-base/src/main/java/org/maxkey/connector/AbstractConnector.java
  32. 33 0
      maxkey-connectors/maxkey-connector-base/src/main/java/org/maxkey/connector/GroupConnector.java
  33. 22 0
      maxkey-connectors/maxkey-connector-base/src/main/java/org/maxkey/connector/OrganizationConnector.java
  34. 13 0
      maxkey-connectors/maxkey-connector-base/src/main/java/org/maxkey/connector/PasswordConnector.java
  35. 23 0
      maxkey-connectors/maxkey-connector-base/src/main/java/org/maxkey/connector/UserInfoConnector.java
  36. 34 0
      maxkey-connectors/maxkey-connector-base/src/main/java/org/maxkey/connector/receiver/KafkaGroupsTopicReceiver.java
  37. 34 0
      maxkey-connectors/maxkey-connector-base/src/main/java/org/maxkey/connector/receiver/KafkaOrgsTopicReceiver.java
  38. 34 0
      maxkey-connectors/maxkey-connector-base/src/main/java/org/maxkey/connector/receiver/KafkaPasswordTopicReceiver.java
  39. 34 0
      maxkey-connectors/maxkey-connector-base/src/main/java/org/maxkey/connector/receiver/KafkaUserInfoTopicReceiver.java
  40. 36 0
      maxkey-connectors/maxkey-connector-ldap/.classpath
  41. 41 0
      maxkey-connectors/maxkey-connector-ldap/.project
  42. 2 0
      maxkey-connectors/maxkey-connector-ldap/.settings/org.eclipse.buildship.core.prefs
  43. 2 0
      maxkey-connectors/maxkey-connector-ldap/.settings/org.eclipse.core.resources.prefs
  44. 14 0
      maxkey-connectors/maxkey-connector-ldap/.settings/org.eclipse.jdt.core.prefs
  45. 3 0
      maxkey-connectors/maxkey-connector-ldap/.settings/org.eclipse.jdt.launching.prefs
  46. 22 0
      maxkey-connectors/maxkey-connector-ldap/.settings/org.eclipse.wst.common.component
  47. 6 0
      maxkey-connectors/maxkey-connector-ldap/.settings/org.eclipse.wst.common.project.facet.core.xml
  48. 2 0
      maxkey-connectors/maxkey-connector-ldap/.settings/org.springframework.ide.eclipse.prefs
  49. 17 0
      maxkey-connectors/maxkey-connector-ldap/build.gradle
  50. 55 0
      maxkey-connectors/maxkey-connector-ldap/src/main/java/org/maxkey/connector/LdapConsumerApplication.java
  51. 153 0
      maxkey-connectors/maxkey-connector-ldap/src/main/java/org/maxkey/connector/ldap/Group2Ldap.java
  52. 119 0
      maxkey-connectors/maxkey-connector-ldap/src/main/java/org/maxkey/connector/ldap/Organization2Ldap.java
  53. 45 0
      maxkey-connectors/maxkey-connector-ldap/src/main/java/org/maxkey/connector/ldap/Password2Ldap.java
  54. 140 0
      maxkey-connectors/maxkey-connector-ldap/src/main/java/org/maxkey/connector/ldap/UserInfo2Ldap.java
  55. 47 0
      maxkey-connectors/maxkey-connector-ldap/src/main/resources/application.properties
  56. 11 0
      maxkey-core/src/main/java/org/maxkey/config/ApplicationConfig.java
  57. 13 0
      maxkey-dao/.settings/org.eclipse.jdt.core.prefs
  58. 1 1
      maxkey-dao/build.gradle
  59. 34 0
      maxkey-dao/src/main/java/org/maxkey/dao/service/OrganizationsService.java
  60. 17 5
      maxkey-dao/src/main/java/org/maxkey/dao/service/UserInfoService.java
  61. 5 0
      maxkey-identitys/.project
  62. 36 0
      maxkey-identitys/maxkey-identity-kafka/.classpath
  63. 41 0
      maxkey-identitys/maxkey-identity-kafka/.project
  64. 2 0
      maxkey-identitys/maxkey-identity-kafka/.settings/org.eclipse.buildship.core.prefs
  65. 2 0
      maxkey-identitys/maxkey-identity-kafka/.settings/org.eclipse.core.resources.prefs
  66. 116 0
      maxkey-identitys/maxkey-identity-kafka/.settings/org.eclipse.jdt.core.prefs
  67. 3 0
      maxkey-identitys/maxkey-identity-kafka/.settings/org.eclipse.jdt.launching.prefs
  68. 16 0
      maxkey-identitys/maxkey-identity-kafka/.settings/org.eclipse.wst.common.component
  69. 6 0
      maxkey-identitys/maxkey-identity-kafka/.settings/org.eclipse.wst.common.project.facet.core.xml
  70. 2 0
      maxkey-identitys/maxkey-identity-kafka/.settings/org.springframework.ide.eclipse.prefs
  71. 15 0
      maxkey-identitys/maxkey-identity-kafka/build.gradle
  72. 10 0
      maxkey-identitys/maxkey-identity-kafka/src/main/java/org/maxkey/identity/kafka/KafkaIdentityAction.java
  73. 11 0
      maxkey-identitys/maxkey-identity-kafka/src/main/java/org/maxkey/identity/kafka/KafkaIdentityTopic.java
  74. 42 0
      maxkey-identitys/maxkey-identity-kafka/src/main/java/org/maxkey/identity/kafka/KafkaMessage.java
  75. 48 0
      maxkey-identitys/maxkey-identity-kafka/src/main/java/org/maxkey/identity/kafka/KafkaProvisioningService.java
  76. 14 0
      maxkey-identitys/maxkey-identity-scim/.settings/org.eclipse.jdt.core.prefs
  77. 3 0
      maxkey-identitys/maxkey-identity-scim/.settings/org.eclipse.jdt.launching.prefs
  78. 13 0
      maxkey-protocols/maxkey-protocol-saml-2.0/.settings/org.eclipse.jdt.core.prefs
  79. 3 0
      maxkey-protocols/maxkey-protocol-saml-2.0/.settings/org.eclipse.jdt.launching.prefs
  80. 1 0
      maxkey-web-manage/.project
  81. 2 1
      maxkey-web-manage/build.gradle
  82. 1 0
      maxkey-web-manage/src/main/java/org/maxkey/MaxKeyMgtApplication.java
  83. 23 1
      maxkey-web-manage/src/main/resources/application.properties
  84. 2 0
      maxkey-web-manage/src/main/resources/maxkey.properties
  85. 22 0
      maxkey-web-maxkey/src/main/resources/application.properties
  86. 3 0
      maxkey-web-maxkey/src/main/resources/maxkey.properties
  87. 7 0
      settings.gradle

+ 1 - 1
.checkstyle

@@ -2,6 +2,6 @@
 
 <fileset-config file-format-version="1.2.0" simple-config="true" sync-formatter="false">
   <fileset name="all" enabled="true" check-config-name="checkstyle-rules" local="false">
-    <file-match-pattern match-pattern=".*" include-pattern="true"/>
+    <file-match-pattern match-pattern="." include-pattern="true"/>
   </fileset>
 </fileset-config>

+ 15 - 2
build.gradle

@@ -31,11 +31,15 @@ allprojects {
 	compileJava.options.encoding = 'UTF-8'
 	
 	eclipse {
+		
 		jdt  {
 		    File f = file('.settings/org.eclipse.core.resources.prefs')
 		    f.write('eclipse.preferences.version=1\n')
 		    f.append('encoding/<project>=UTF-8') //use UTF-8
-		}/*
+		}
+		/**/
+		
+		/*
 		wtp {
 	        facet {
 	            facet name: 'jst.web', type: Facet.FacetType.fixed
@@ -174,7 +178,7 @@ subprojects {
          //compile group: 'org.springframework', name: 'spring-jcl', version: "${springVersion}"
          compile group: 'org.springframework', name: 'spring-jdbc', version: "${springVersion}"
          //compile group: 'org.springframework', name: 'spring-jms', version: "${springVersion}"
-         //compile group: 'org.springframework', name: 'spring-messaging', version: "${springVersion}"
+         compile group: 'org.springframework', name: 'spring-messaging', version: "${springVersion}"
          //compile group: 'org.springframework', name: 'spring-orm', version: "${springVersion}"
          compile group: 'org.springframework', name: 'spring-oxm', version: "${springVersion}"
          compile group: 'org.springframework', name: 'spring-tx', version: "${springVersion}"
@@ -183,6 +187,15 @@ subprojects {
          compile group: 'org.springframework', name: 'spring-webmvc', version: "${springVersion}"
          //compile group: 'org.springframework', name: 'spring-websocket', version: "${springVersion}"
 		 testCompile group: 'org.springframework', name: 'spring-test', version: "${springVersion}"
+		 
+		 // https://mvnrepository.com/artifact/org.apache.kafka/kafka-clients
+		 compile group: 'org.apache.kafka', name: 'kafka-clients', version: '2.5.0'
+		 // https://mvnrepository.com/artifact/org.springframework.kafka/spring-kafka
+		 compile group: 'org.springframework.kafka', name: 'spring-kafka', version: '2.5.2.RELEASE'
+		 // https://mvnrepository.com/artifact/org.springframework.retry/spring-retry
+		 compile group: 'org.springframework.retry', name: 'spring-retry', version: '1.3.0'
+		 
+		 
          //spring-security
          compile group: 'org.springframework.security', name: 'spring-security-core', version: "${springSecurityVersion}"
          compile group: 'org.springframework.security', name: 'spring-security-web', version: "${springSecurityVersion}"

+ 6 - 0
maxkey-connectors/.classpath

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
+	<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
+	<classpathentry kind="output" path="bin/default"/>
+</classpath>

+ 28 - 0
maxkey-connectors/.project

@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>maxkey-connectors</name>
+	<comment>Project maxkey-connectors created by Buildship.</comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.springframework.ide.eclipse.boot.validation.springbootbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
+	</natures>
+</projectDescription>

+ 36 - 0
maxkey-connectors/maxkey-connector-activedirectory/.classpath

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="bin/main" path="src/main/java">
+		<attributes>
+			<attribute name="gradle_scope" value="main"/>
+			<attribute name="gradle_used_by_scope" value="main,test"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="bin/main" path="src/main/resources">
+		<attributes>
+			<attribute name="gradle_scope" value="main"/>
+			<attribute name="gradle_used_by_scope" value="main,test"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="bin/test" path="src/test/java">
+		<attributes>
+			<attribute name="gradle_scope" value="test"/>
+			<attribute name="gradle_used_by_scope" value="test"/>
+			<attribute name="test" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="bin/test" path="src/test/resources">
+		<attributes>
+			<attribute name="gradle_scope" value="test"/>
+			<attribute name="gradle_used_by_scope" value="test"/>
+			<attribute name="test" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
+	<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer">
+		<attributes>
+			<attribute name="org.eclipse.jst.component.nondependency" value=""/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="bin/default"/>
+</classpath>

+ 41 - 0
maxkey-connectors/maxkey-connector-activedirectory/.project

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>maxkey-connector-activedirectory</name>
+	<comment>Project maxkey-connectors-activedirectory created by Buildship.</comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.springframework.ide.eclipse.boot.validation.springbootbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
+		<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
+		<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
+	</natures>
+</projectDescription>

+ 2 - 0
maxkey-connectors/maxkey-connector-activedirectory/.settings/org.eclipse.buildship.core.prefs

@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1

+ 2 - 0
maxkey-connectors/maxkey-connector-activedirectory/.settings/org.eclipse.core.resources.prefs

@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/<project>=UTF-8

+ 14 - 0
maxkey-connectors/maxkey-connector-activedirectory/.settings/org.eclipse.jdt.core.prefs

@@ -0,0 +1,14 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=warning
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.mainOnlyProjectHasTestOnlyDependency=error
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.classpath.outputOverlappingAnotherSource=error
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error

+ 3 - 0
maxkey-connectors/maxkey-connector-activedirectory/.settings/org.eclipse.jdt.launching.prefs

@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.launching.PREF_COMPILER_COMPLIANCE_DOES_NOT_MATCH_JRE=warning
+org.eclipse.jdt.launching.PREF_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE=warning

+ 22 - 0
maxkey-connectors/maxkey-connector-activedirectory/.settings/org.eclipse.wst.common.component

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-modules id="moduleCoreId" project-version="1.5.0">
+	<wb-module deploy-name="maxkey-connector-activedirectory">
+		<wb-resource deploy-path="/" source-path="src/main/resources"/>
+		<wb-resource deploy-path="/" source-path="src/main/java"/>
+		<dependent-module deploy-path="../" handle="module:/resource/maxkey-core/maxkey-core">
+			<dependency-type>uses</dependency-type>
+		</dependent-module>
+		<dependent-module deploy-path="../" handle="module:/resource/maxkey-dao/maxkey-dao">
+			<dependency-type>uses</dependency-type>
+		</dependent-module>
+		<dependent-module deploy-path="../" handle="module:/resource/maxkey-client-sdk/maxkey-client-sdk">
+			<dependency-type>uses</dependency-type>
+		</dependent-module>
+		<dependent-module deploy-path="../" handle="module:/resource/maxkey-connector-base/maxkey-connector-base">
+			<dependency-type>uses</dependency-type>
+		</dependent-module>
+		<dependent-module deploy-path="../" handle="module:/resource/maxkey-identity-kafka/maxkey-identity-kafka">
+			<dependency-type>uses</dependency-type>
+		</dependent-module>
+	</wb-module>
+</project-modules>

+ 6 - 0
maxkey-connectors/maxkey-connector-activedirectory/.settings/org.eclipse.wst.common.project.facet.core.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+	<fixed facet="jst.java"/>
+	<installed facet="jst.utility" version="1.0"/>
+	<installed facet="jst.java" version="1.8"/>
+</faceted-project>

+ 2 - 0
maxkey-connectors/maxkey-connector-activedirectory/.settings/org.springframework.ide.eclipse.prefs

@@ -0,0 +1,2 @@
+boot.validation.initialized=true
+eclipse.preferences.version=1

+ 17 - 0
maxkey-connectors/maxkey-connector-activedirectory/build.gradle

@@ -0,0 +1,17 @@
+description = "maxkey-connector-activedirectory"
+
+apply plugin: 'java'
+apply plugin: 'eclipse-wtp'
+
+
+dependencies {
+	//local jars
+	compile fileTree(dir: '../maxkey-lib/*/', include: '*.jar')
+	
+	compile project(":maxkey-core")
+	compile project(":maxkey-dao")
+   	compile project(":maxkey-client-sdk")
+   	compile project(":maxkey-connectors:maxkey-connector-base")
+   	compile project(":maxkey-identitys:maxkey-identity-kafka")
+   
+}

+ 56 - 0
maxkey-connectors/maxkey-connector-activedirectory/src/main/java/org/maxkey/connector/ActivedirectoryConsumerApplication.java

@@ -0,0 +1,56 @@
+package org.maxkey.connector;
+
+import org.maxkey.constants.ConstantsProperties;
+import org.maxkey.persistence.ldap.ActiveDirectoryUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+
+@Configuration
+@PropertySource(ConstantsProperties.applicationPropertySource)
+@SpringBootApplication
+@ComponentScan(basePackages = {
+        "org.maxkey.connector",
+        "org.maxkey.connector.receiver",
+        "org.maxkey.connector.activedirectory"
+    })
+public class ActivedirectoryConsumerApplication {
+
+	public static void main(String[] args) {
+	    ConfigurableApplicationContext context = SpringApplication.run(ActivedirectoryConsumerApplication.class, args);
+		  
+	}
+	
+	//@Bean(name = "activeDirectoryUtils")
+	public ActiveDirectoryUtils getLdapConnection(
+			@Value("${config.connector.activedirectory.providerUrl}") String providerUrl,
+			@Value("${config.connector.activedirectory.principal}") String principal,
+			@Value("${config.connector.activedirectory.credentials}") String credentials,
+			@Value("${config.connector.activedirectory.baseDN}") String baseDn,
+			@Value("${config.connector.activedirectory.domain}") String domain,
+			@Value("${config.connector.activedirectory.trustStore}") String trustStore,
+			@Value("${config.connector.activedirectory.trustStore.password}") String trustStorePassword
+			)throws Exception{
+		ActiveDirectoryUtils ldapUtils=new ActiveDirectoryUtils(
+				providerUrl,
+				principal,
+				credentials,
+				baseDn,
+				domain);
+		
+		ldapUtils.setTrustStore(trustStore);
+		ldapUtils.setTrustStorePassword(trustStorePassword);
+		ldapUtils.setSsl(true);
+		
+		if(ldapUtils.openConnection()==null){
+			 throw new Exception("connection to Ldap Error.");   
+		}
+		return ldapUtils;
+	}
+
+}

+ 181 - 0
maxkey-connectors/maxkey-connector-activedirectory/src/main/java/org/maxkey/connector/activedirectory/Group2Activedirectory.java

@@ -0,0 +1,181 @@
+package org.maxkey.connector.activedirectory;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.ModificationItem;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+
+import org.maxkey.connector.GroupConnector;
+import org.maxkey.domain.GroupMember;
+import org.maxkey.domain.Groups;
+import org.maxkey.persistence.ldap.ActiveDirectoryUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+@Component(value = "groupConnector")
+public class Group2Activedirectory extends GroupConnector {
+	private final static Logger logger = LoggerFactory.getLogger(Group2Activedirectory.class);
+
+	ActiveDirectoryUtils  ldapUtils;
+	
+	public Group2Activedirectory() {
+		// TODO Auto-generated constructor stub
+	}
+	@Override
+	public boolean create(Groups group)  throws Exception{
+		logger.info("create");
+		try {
+			Attributes attributes = new BasicAttributes();
+			Attribute objectClass = new BasicAttribute("objectClass");
+			objectClass.add("top");
+			objectClass.add("group");
+			attributes.put(objectClass);
+			
+			attributes.put(new BasicAttribute("cn",group.getName()));
+			attributes.put(new BasicAttribute("member","CN=dummy,"+ldapUtils.getBaseDN()));
+			
+			String dn="cn="+group.getName()+",cn=groups,"+ldapUtils.getBaseDN();
+		
+			ldapUtils.getCtx().createSubcontext(dn, attributes);
+			ldapUtils.close();
+		} catch (NamingException e) {
+			e.printStackTrace();
+		}
+		return true;
+	}
+
+	@Override
+	public boolean update(Groups group)  throws Exception{
+		logger.info("update");
+		try {
+			SearchControls constraints = new SearchControls();
+			constraints.setSearchScope(ldapUtils.getSearchScope());
+			NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
+					.search(ldapUtils.getBaseDN(), "(cn="+group.getName()+")", constraints);
+			String oldDn="";
+			String rdn="";
+			if (results == null || !results.hasMore()) {
+				return create(group);
+			}else{
+				SearchResult sr = (SearchResult) results.next();
+				oldDn =sr.getNameInNamespace();
+				String[] dnSplit=oldDn.split(",");
+				rdn=oldDn.substring(oldDn.indexOf(","), oldDn.length());
+				
+				String groupName=dnSplit[0].split("=")[1];
+				if(group.getName()!=groupName){
+					String newDn="cn="+group.getName()+","+rdn;
+					ldapUtils.getCtx().rename(oldDn, newDn);
+					ModificationItem[] modificationItems = new ModificationItem[1];
+					modificationItems[0]=new ModificationItem(DirContext.REMOVE_ATTRIBUTE,new BasicAttribute("cn",groupName));
+					ldapUtils.getCtx().modifyAttributes(newDn, modificationItems);
+				}
+			}
+			
+			ldapUtils.close();
+		} catch (NamingException e) {
+			e.printStackTrace();
+		}
+		return true;
+	}
+
+	@Override
+	public boolean delete(Groups group) throws Exception {
+		logger.info("delete");
+		try {
+			String dn="cn="+group.getName()+",cn=groups,"+ldapUtils.getBaseDN();
+			ldapUtils.getCtx().destroySubcontext(dn);
+			ldapUtils.close();
+		} catch (NamingException e) {
+			e.printStackTrace();
+		}
+		return true;
+	}
+
+	@Override
+	public boolean addMember(GroupMember groupMember) throws Exception {
+		try {
+			SearchControls constraints = new SearchControls();
+			constraints.setSearchScope(ldapUtils.getSearchScope());
+			NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
+					.search(ldapUtils.getBaseDN(), "(cn="+groupMember.getGroupName()+")", constraints);
+			if (results == null || !results.hasMore()) {
+				Groups  group =new Groups();
+				group.setName(groupMember.getGroupName());
+				return create(group);
+			}
+			
+			
+			String uniqueMember="";
+			SearchControls memberSearchControls = new SearchControls();
+			logger.debug("user Search : "+"(sAMAccountName="+groupMember.getMemberName()+")");
+			memberSearchControls.setSearchScope(ldapUtils.getSearchScope());
+			NamingEnumeration<SearchResult> memberResults = ldapUtils.getConnection()
+					.search(ldapUtils.getBaseDN(), "(sAMAccountName="+groupMember.getMemberName()+")", memberSearchControls);
+			if (memberResults == null || !memberResults.hasMore()) {
+				
+			}else{
+				SearchResult memberSr = (SearchResult) memberResults.next();
+				uniqueMember =memberSr.getNameInNamespace();
+				logger.debug("uniqueMember : "+uniqueMember);
+				ModificationItem[] modificationItems = new ModificationItem[1];
+				modificationItems[0]=new ModificationItem(DirContext.ADD_ATTRIBUTE,new BasicAttribute("member",uniqueMember));
+				
+				String dn="cn="+groupMember.getGroupName()+",cn=groups,"+ldapUtils.getBaseDN();
+				
+				ldapUtils.getCtx().modifyAttributes(dn, modificationItems);
+			}
+			
+			
+			ldapUtils.close();
+		} catch (NamingException e) {
+			e.printStackTrace();
+		}
+		return true;
+	}
+
+	@Override
+	public boolean deleteMember(GroupMember groupMember)  throws Exception{
+		try {
+			SearchControls constraints = new SearchControls();
+			constraints.setSearchScope(ldapUtils.getSearchScope());
+			NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
+					.search(ldapUtils.getBaseDN(), "(cn="+groupMember.getGroupName()+")", constraints);
+			if (results == null || !results.hasMore()) {
+				return true;
+			}
+			
+			String uniqueMember="";
+			SearchControls memberSearchControls = new SearchControls();
+			memberSearchControls.setSearchScope(ldapUtils.getSearchScope());
+			NamingEnumeration<SearchResult> memberResults = ldapUtils.getConnection()
+					.search(ldapUtils.getBaseDN(), "(sAMAccountName="+groupMember.getMemberName()+")", memberSearchControls);
+			if (memberResults == null || !memberResults.hasMore()) {
+				
+			}else{
+				SearchResult memberSr = (SearchResult) memberResults.next();
+				uniqueMember =memberSr.getNameInNamespace();
+				logger.debug("uniqueMember : "+uniqueMember);
+				ModificationItem[] modificationItems = new ModificationItem[1];
+				modificationItems[0]=new ModificationItem(DirContext.REMOVE_ATTRIBUTE,new BasicAttribute("member",uniqueMember));
+				
+				String dn="cn="+groupMember.getGroupName()+",cn=groups,"+ldapUtils.getBaseDN();
+				
+				ldapUtils.getCtx().modifyAttributes(dn, modificationItems);
+			}
+
+			ldapUtils.close();
+		} catch (NamingException e) {
+			e.printStackTrace();
+		}
+		return true;
+	}
+	
+}

+ 124 - 0
maxkey-connectors/maxkey-connector-activedirectory/src/main/java/org/maxkey/connector/activedirectory/Organization2Activedirectory.java

@@ -0,0 +1,124 @@
+package org.maxkey.connector.activedirectory;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+
+import org.maxkey.connector.OrganizationConnector;
+import org.maxkey.domain.Organizations;
+import org.maxkey.persistence.ldap.ActiveDirectoryUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+@Component(value = "organizationConnector")
+public class Organization2Activedirectory  extends OrganizationConnector{
+	private final static Logger logger = LoggerFactory.getLogger(Organization2Activedirectory.class);
+
+	ActiveDirectoryUtils  ldapUtils;
+	
+	public Organization2Activedirectory() {
+		// TODO Auto-generated constructor stub
+	}
+
+	@Override
+	public boolean create(Organizations organization) throws Exception {
+		try {
+			SearchControls constraints = new SearchControls();
+			constraints.setSearchScope(ldapUtils.getSearchScope());
+			NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
+					.search(ldapUtils.getBaseDN(), "(&(objectClass=organizationalUnit)(description="+organization.getpId()+"))", constraints);
+			String rdn="";
+			if (results == null || !results.hasMore()) {
+				rdn=ldapUtils.getBaseDN();
+			}else{
+				SearchResult sr = (SearchResult) results.next();
+				rdn =sr.getNameInNamespace();
+			}
+			
+			Attributes attributes = new BasicAttributes();
+			attributes.put(new BasicAttribute("objectClass","organizationalUnit"));
+			attributes.put(new BasicAttribute("ou",organization.getName()));
+			//attributes.put(new BasicAttribute("name",organization.getName()));
+			//attributes.put(new BasicAttribute("id",organization.getId()));
+			//attributes.put(new BasicAttribute("porgname",organization.getpName()));
+			//attributes.put(new BasicAttribute("porgid",organization.getpId()));
+			attributes.put(new BasicAttribute("description",organization.getId()));
+			
+			String dn="ou="+organization.getName()+","+rdn;
+			
+			ldapUtils.getCtx().createSubcontext(dn, attributes);
+			ldapUtils.close();
+			
+		} catch (NamingException e) {
+			e.printStackTrace();
+		}
+		return super.create(organization);
+	}
+
+	@Override
+	public boolean update(Organizations organization)  throws Exception{
+		try {
+			SearchControls constraints = new SearchControls();
+			constraints.setSearchScope(ldapUtils.getSearchScope());
+			NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
+					.search(ldapUtils.getBaseDN(), "(&(objectClass=organizationalUnit)(description="+organization.getId()+"))", constraints);
+			String oldDn="";
+			String rdn="";
+			if (results == null || !results.hasMore()) {
+				return create(organization);
+			}else{
+				SearchResult sr = (SearchResult) results.next();
+				oldDn =sr.getNameInNamespace();
+				String[] dnSplit=oldDn.split(",");
+				rdn=oldDn.substring(oldDn.indexOf(",")+1, oldDn.length());
+				
+				String ouName=dnSplit[0].split("=")[1];
+				if(organization.getName()!=ouName){
+					String newDn="ou="+organization.getName()+","+rdn;
+					logger.debug("oldDn : "+oldDn);
+					logger.debug("newDn : "+newDn);
+					ldapUtils.getCtx().rename(oldDn, newDn);
+					
+					//ModificationItem[] modificationItems = new ModificationItem[1];
+					//modificationItems[0]=new ModificationItem(DirContext.REMOVE_ATTRIBUTE,new BasicAttribute("ou",ouName));
+					//modificationItems[0]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("name",organization.getName()));
+					//ldapUtils.getCtx().modifyAttributes(newDn, modificationItems);
+				}
+			}
+			
+			ldapUtils.close();
+		} catch (NamingException e) {
+			e.printStackTrace();
+		}
+		return super.update(organization);
+	}
+
+	@Override
+	public boolean delete(Organizations organization) throws Exception {
+		try {
+			SearchControls constraints = new SearchControls();
+			constraints.setSearchScope(ldapUtils.getSearchScope());
+			NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
+					.search(ldapUtils.getBaseDN(), "(&(objectClass=organizationalUnit)(description="+organization.getId()+"))", constraints);
+			String dn="";
+			if (results == null || !results.hasMore()) {
+				
+			}else{
+				SearchResult sr = (SearchResult) results.next();
+				dn =sr.getNameInNamespace();
+				ldapUtils.getCtx().destroySubcontext(dn);
+			}
+			
+			ldapUtils.close();
+		} catch (NamingException e) {
+			e.printStackTrace();
+		}
+		return super.delete(organization);
+	}	
+	
+}

+ 86 - 0
maxkey-connectors/maxkey-connector-activedirectory/src/main/java/org/maxkey/connector/activedirectory/Password2Activedirectory.java

@@ -0,0 +1,86 @@
+package org.maxkey.connector.activedirectory;
+
+import java.io.UnsupportedEncodingException;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.ModificationItem;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+
+import org.maxkey.connector.PasswordConnector;
+import org.maxkey.crypto.ReciprocalUtils;
+import org.maxkey.domain.UserInfo;
+import org.maxkey.persistence.ldap.ActiveDirectoryUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+@Component(value = "passwordConnector")
+public class Password2Activedirectory  extends PasswordConnector{
+	private final static Logger logger = LoggerFactory.getLogger(Password2Activedirectory.class);
+	ActiveDirectoryUtils  ldapUtils;
+	/**
+	 * userAccountControl鍊煎緱璇存槑
+	 * http://support.microsoft.com/zh-cn/kb/305144
+	 *  灞炴�ф爣蹇�	鍗佸叚杩涘埗鍊�	鍗佽繘鍒跺��
+		SCRIPT	0x0001	1
+		ACCOUNTDISABLE	0x0002	2
+		HOMEDIR_REQUIRED	0x0008	8
+		LOCKOUT	0x0010	16
+		PASSWD_NOTREQD	0x0020	32
+		PASSWD_CANT_CHANGE	0x0040	64
+		ENCRYPTED_TEXT_PWD_ALLOWED	0x0080	128
+		TEMP_DUPLICATE_ACCOUNT	0x0100	256
+		NORMAL_ACCOUNT	0x0200	512
+		INTERDOMAIN_TRUST_ACCOUNT	0x0800	2048
+		WORKSTATION_TRUST_ACCOUNT	0x1000	4096
+		SERVER_TRUST_ACCOUNT	0x2000	8192
+		DONT_EXPIRE_PASSWORD	0x10000	65536
+		MNS_LOGON_ACCOUNT	0x20000	131072
+		SMARTCARD_REQUIRED	0x40000	262144
+		TRUSTED_FOR_DELEGATION	0x80000	524288
+		NOT_DELEGATED	0x100000	1048576
+		USE_DES_KEY_ONLY	0x200000	2097152
+		DONT_REQ_PREAUTH	0x400000	4194304
+		PASSWORD_EXPIRED	0x800000	8388608
+		TRUSTED_TO_AUTH_FOR_DELEGATION	0x1000000	16777216
+	 */
+	public Password2Activedirectory() {
+		
+	}
+	
+	@Override
+	public boolean sync(UserInfo userInfo) throws Exception{
+		try {
+			String dn=null;
+			SearchControls searchControls = new SearchControls();
+			searchControls.setSearchScope(ldapUtils.getSearchScope());
+			NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
+					.search(ldapUtils.getBaseDN(), "(sAMAccountName="+userInfo.getUsername()+")", searchControls);
+			if (results == null || !results.hasMore()) {
+				
+			}else{
+				SearchResult sr = (SearchResult) results.next();
+				dn =sr.getNameInNamespace();
+				ModificationItem[] modificationItems = new ModificationItem[1];
+				logger.info("decipherable : "+userInfo.getDecipherable());
+				String password=ReciprocalUtils.decoder(userInfo.getDecipherable());
+				//modificationItems[0]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("userPassword",password));
+				modificationItems[0]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("unicodePwd",("\"" + password + "\"").getBytes("UTF-16LE")));
+				
+				ldapUtils.getCtx().modifyAttributes(dn, modificationItems);
+			}
+			
+			ldapUtils.close();
+		} catch (NamingException e) {
+			e.printStackTrace();
+		} catch (UnsupportedEncodingException e) {
+			e.printStackTrace();
+		}
+		return true;
+	}
+
+	
+}

+ 271 - 0
maxkey-connectors/maxkey-connector-activedirectory/src/main/java/org/maxkey/connector/activedirectory/UserInfo2Activedirectory.java

@@ -0,0 +1,271 @@
+package org.maxkey.connector.activedirectory;
+
+import java.io.UnsupportedEncodingException;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.ModificationItem;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+
+import org.maxkey.connector.UserInfoConnector;
+import org.maxkey.crypto.ReciprocalUtils;
+import org.maxkey.domain.UserInfo;
+import org.maxkey.persistence.ldap.ActiveDirectoryUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+@Component(value = "userInfoConnector")
+public class UserInfo2Activedirectory  extends UserInfoConnector{
+	private final static Logger logger = LoggerFactory.getLogger(UserInfo2Activedirectory.class);
+	ActiveDirectoryUtils  ldapUtils;
+	/**
+	 * userAccountControl值得说明
+	 * http://support.microsoft.com/zh-cn/kb/305144
+	 *  属�?�标�?	十六进制�?	十进制�??
+		SCRIPT	0x0001	1
+		ACCOUNTDISABLE	0x0002	2
+		HOMEDIR_REQUIRED	0x0008	8
+		LOCKOUT	0x0010	16
+		PASSWD_NOTREQD	0x0020	32
+		PASSWD_CANT_CHANGE	0x0040	64
+		ENCRYPTED_TEXT_PWD_ALLOWED	0x0080	128
+		TEMP_DUPLICATE_ACCOUNT	0x0100	256
+		NORMAL_ACCOUNT	0x0200	512
+		INTERDOMAIN_TRUST_ACCOUNT	0x0800	2048
+		WORKSTATION_TRUST_ACCOUNT	0x1000	4096
+		SERVER_TRUST_ACCOUNT	0x2000	8192
+		DONT_EXPIRE_PASSWORD	0x10000	65536
+		MNS_LOGON_ACCOUNT	0x20000	131072
+		SMARTCARD_REQUIRED	0x40000	262144
+		TRUSTED_FOR_DELEGATION	0x80000	524288
+		NOT_DELEGATED	0x100000	1048576
+		USE_DES_KEY_ONLY	0x200000	2097152
+		DONT_REQ_PREAUTH	0x400000	4194304
+		PASSWORD_EXPIRED	0x800000	8388608
+		TRUSTED_TO_AUTH_FOR_DELEGATION	0x1000000	16777216
+	 */
+	public UserInfo2Activedirectory() {
+		
+	}
+
+	@Override
+	public boolean create(UserInfo userInfo) throws Exception{
+		try {
+			Attributes attributes = new BasicAttributes();
+			Attribute objectClass = new BasicAttribute("objectClass");
+			objectClass.add("top");
+			objectClass.add("person");
+			objectClass.add("organizationalPerson");
+			objectClass.add("user");
+			attributes.put(objectClass);
+			attributes.put(new BasicAttribute("sAMAccountName",userInfo.getUsername()));
+			logger.debug("decipherable : "+userInfo.getDecipherable());
+			String password=ReciprocalUtils.decoder(userInfo.getDecipherable());
+			
+			attributes.put(new BasicAttribute("unicodePwd",("\"" + password + "\"").getBytes("UTF-16LE")));
+			//attributes.put(new BasicAttribute("cn",userInfo.getDisplayName()));
+			attributes.put(new BasicAttribute("cn",userInfo.getUsername()));
+			attributes.put(new BasicAttribute("displayName",userInfo.getDisplayName()));
+			attributes.put(new BasicAttribute("givenName",userInfo.getGivenName()));
+			attributes.put(new BasicAttribute("sn",userInfo.getFamilyName()));
+
+			attributes.put(new BasicAttribute("mobile",userInfo.getWorkPhoneNumber()==null?"00000000000":userInfo.getWorkPhoneNumber()));
+			attributes.put(new BasicAttribute("mail",userInfo.getWorkEmail()==null?"email@default.com":userInfo.getWorkEmail()));
+		
+			attributes.put(new BasicAttribute("employeeNumber",userInfo.getEmployeeNumber()==null?"0":userInfo.getEmployeeNumber()));
+			attributes.put(new BasicAttribute("ou",userInfo.getDepartment()==null?"default":userInfo.getDepartment()));
+			String managerDn="CN=dummy,"+ldapUtils.getBaseDN();
+			if(userInfo.getManagerId()==null||userInfo.getManagerId().equals("")){
+				logger.debug("manager is null.");
+			}else{
+				UserInfo queryManager=new UserInfo();
+				queryManager.setId(userInfo.getManagerId());
+				UserInfo manager=loadUser(queryManager);
+				SearchControls managerSearchControls = new SearchControls();
+				managerSearchControls.setSearchScope(ldapUtils.getSearchScope());
+				logger.debug("managerResults : "+ldapUtils.getBaseDN());
+				logger.debug("filter : "+"(sAMAccountName="+manager.getUsername()+")");
+				logger.debug("managerSearchControls : "+managerSearchControls);
+				NamingEnumeration<SearchResult> managerResults = ldapUtils.getConnection()
+						.search(ldapUtils.getBaseDN(), "(sAMAccountName="+manager.getUsername()+")", managerSearchControls);
+				if (managerResults == null || !managerResults.hasMore()) {
+					
+				}else{
+					SearchResult managerSr = (SearchResult) managerResults.next();
+					managerDn =managerSr.getNameInNamespace();
+				}
+			}
+			
+			attributes.put(new BasicAttribute("manager",managerDn));
+			
+			attributes.put(new BasicAttribute("department",userInfo.getDepartment()==null?"default":userInfo.getDepartment()));
+			attributes.put(new BasicAttribute("departmentNumber",userInfo.getDepartmentId()==null?"default":userInfo.getDepartmentId()));
+			attributes.put(new BasicAttribute("title",userInfo.getJobTitle()==null?"default":userInfo.getJobTitle()));
+			
+			//for kerberos login
+			attributes.put(new BasicAttribute("servicePrincipalName",this.properties.getProperty("servicePrincipalName")));
+			attributes.put(new BasicAttribute("userPrincipalName",userInfo.getUsername()+"@"+this.properties.getProperty("domain")));
+			
+			attributes.put(new BasicAttribute("userAccountControl",Integer.toString(66048)));
+			String rdn="";
+			if(userInfo.getDepartmentId()!=null&&
+					!userInfo.getDepartmentId().equals("")){
+				//get organization dn
+				SearchControls searchControls = new SearchControls();
+				searchControls.setSearchScope(ldapUtils.getSearchScope());
+				logger.debug("managerResults : "+ldapUtils.getBaseDN());
+				logger.debug("filter  : "+"(&(objectClass=organizationalUnit)(description="+userInfo.getDepartmentId()+"))");
+				logger.debug("searchControls : "+searchControls);
+				NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
+						.search(ldapUtils.getBaseDN(), "(&(objectClass=organizationalUnit)(description="+userInfo.getDepartmentId()+"))", searchControls);
+				
+				if (results == null || !results.hasMore()) {
+					rdn=ldapUtils.getBaseDN();
+				}else{
+					SearchResult sr = (SearchResult) results.next();
+					rdn =sr.getNameInNamespace();
+				}
+			}else{
+				rdn=ldapUtils.getBaseDN();
+			}
+			
+			//String dn="CN="+userInfo.getDisplayName()+","+rdn;
+			String dn="CN="+userInfo.getUsername()+","+rdn;
+		
+			logger.debug("dn : "+dn);
+			ldapUtils.getCtx().createSubcontext(dn, attributes);
+			ldapUtils.close();
+			super.create(userInfo);
+		} catch (NamingException e) {
+			e.printStackTrace();
+		} catch (UnsupportedEncodingException e) {
+			e.printStackTrace();
+		}
+		return true;
+	}
+	
+	@Override
+	public boolean update(UserInfo userInfo) throws Exception{
+		try {
+			String dn=null;
+			SearchControls searchControls = new SearchControls();
+			searchControls.setSearchScope(ldapUtils.getSearchScope());
+			NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
+					.search(ldapUtils.getBaseDN(), "(sAMAccountName="+userInfo.getUsername()+")", searchControls);
+			if (results == null || !results.hasMore()) {
+				return create(loadUser(userInfo));
+			}
+			
+			SearchResult sr = (SearchResult) results.next();
+			dn =sr.getNameInNamespace();
+			
+			ModificationItem[] modificationItems = new ModificationItem[8];
+			//modificationItems[0]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("displayName",userInfo.getDisplayName()));
+			//modificationItems[1]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("cn",userInfo.getDisplayName()));
+			//modificationItems[2]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("givenName",userInfo.getGivenName()));
+			//modificationItems[3]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("sn",userInfo.getFamilyName()));
+			
+			modificationItems[0]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("mobile",userInfo.getWorkPhoneNumber()==null?"00000000000":userInfo.getWorkPhoneNumber()));
+			modificationItems[1]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("mail",userInfo.getWorkEmail()==null?"email@default.com":userInfo.getWorkEmail()));
+			
+			modificationItems[2]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("employeeNumber",userInfo.getEmployeeNumber()==null?"default":userInfo.getEmployeeNumber()));
+			modificationItems[3]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("ou",userInfo.getDepartment()==null?"default":userInfo.getDepartment()));
+			
+			modificationItems[4]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("department",userInfo.getDepartmentId()==null?"default":userInfo.getDepartment()));
+			modificationItems[5]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("departmentNumber",userInfo.getDepartmentId()==null?"default":userInfo.getDepartmentId()));
+			modificationItems[6]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("title",userInfo.getJobTitle()==null?"default":userInfo.getJobTitle()));
+			
+			String managerDn="CN=dummy,"+ldapUtils.getBaseDN();
+			if(userInfo.getManagerId()==null||userInfo.getManagerId().equals("")){
+
+			}else{
+				UserInfo queryManager=new UserInfo();
+				queryManager.setId(userInfo.getManagerId());
+				UserInfo manager=loadUser(queryManager);
+				SearchControls managerSearchControls = new SearchControls();
+				managerSearchControls.setSearchScope(ldapUtils.getSearchScope());
+				NamingEnumeration<SearchResult> managerResults = ldapUtils.getConnection()
+						.search(ldapUtils.getBaseDN(), "(sAMAccountName="+manager.getUsername()+")", managerSearchControls);
+				if (managerResults == null || !managerResults.hasMore()) {
+					
+				}else{
+					SearchResult managerSr = (SearchResult) managerResults.next();
+					managerDn =managerSr.getNameInNamespace();
+				}
+			}
+			
+			modificationItems[7]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("manager",managerDn));
+			
+			
+			ldapUtils.getCtx().modifyAttributes(dn, modificationItems);
+			
+			if(userInfo.getDepartmentId()!=null&&
+					!userInfo.getDepartmentId().equals("")){
+				//get organization dn
+				SearchControls orgSearchControls = new SearchControls();
+				orgSearchControls.setSearchScope(ldapUtils.getSearchScope());
+				NamingEnumeration<SearchResult> orgResults = ldapUtils.getConnection()
+						.search(ldapUtils.getBaseDN(), "(&(objectClass=organizationalUnit)(description="+userInfo.getDepartmentId()+"))", orgSearchControls);
+				String orgRdn="";
+				if (orgResults == null || !orgResults.hasMore()) {
+					orgRdn=ldapUtils.getBaseDN();
+				}else{
+					SearchResult orgSearchResult = (SearchResult) orgResults.next();
+					orgRdn =orgSearchResult.getNameInNamespace();
+				}
+				
+				//String newDn="CN="+userInfo.getDisplayName()+","+orgRdn;
+				String newDn="CN="+userInfo.getUsername()+","+orgRdn;
+				
+				if(!dn.equals(newDn)){
+					logger.debug("oldDn : "+dn);
+					logger.debug("newDn : "+newDn);
+					ldapUtils.getCtx().rename(dn, newDn);
+				}
+			}
+			
+			ldapUtils.close();
+		} catch (NamingException e) {
+			e.printStackTrace();
+		}
+		return true;
+	}
+	
+	@Override
+	public boolean delete(UserInfo userInfo) throws Exception{
+		try {
+			String dn=null;
+			SearchControls searchControls = new SearchControls();
+			searchControls.setSearchScope(ldapUtils.getSearchScope());
+			NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
+					.search(ldapUtils.getBaseDN(), "(sAMAccountName="+userInfo.getUsername()+")", searchControls);
+			if (results == null || !results.hasMore()) {
+				
+			}else{
+				SearchResult sr = (SearchResult) results.next();
+				dn =sr.getNameInNamespace();
+				logger.debug("delete dn : "+dn);
+				ldapUtils.getCtx().destroySubcontext(dn);
+			}
+			
+			ldapUtils.close();
+			super.delete(userInfo);
+		} catch (NamingException e) {
+			e.printStackTrace();
+		} 
+		return true;
+	}
+	
+
+	public UserInfo loadUser(UserInfo UserInfo) {
+		return null;
+	}
+	
+	
+}

+ 48 - 0
maxkey-connectors/maxkey-connector-activedirectory/src/main/resources/application.properties

@@ -0,0 +1,48 @@
+#spring.profiles.active=dev
+#application
+application.title=MaxKey-Connector-ActiveDirectory
+application.name=MaxKey-Connector-ActiveDirectory
+application.formatted-version=v2.0.0 GA
+#server port
+server.port=9602
+#datasource
+spring.datasource.username=root
+spring.datasource.password=maxkey
+spring.datasource.url=jdbc:mysql://localhost/maxkey?autoReconnect=true&characterEncoding=UTF-8
+spring.datasource.driver-class-name=com.mysql.jdbc.Driver
+spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
+
+spring.kafka.bootstrap-servers=localhost:9092
+###########【初始化消费者配置】###########
+# 默认的消费组ID
+spring.kafka.consumer.properties.group.id=defaultConsumerGroup
+# 是否自动提交offset
+spring.kafka.consumer.enable-auto-commit=true
+# 提交offset延时(接收到消息后多久提交offset)
+spring.kafka.consumer.auto.commit.interval.ms=1000
+# 当kafka中没有初始offset或offset超出范围时将自动重置offset
+# earliest:重置为分区中最小的offset;
+# latest:重置为分区中最新的offset(消费分区中新产生的数据);
+# none:只要有一个分区不存在已提交的offset,就抛出异常;
+spring.kafka.consumer.auto-offset-reset=latest
+# 消费会话超时时间(超过这个时间consumer没有发送心跳,就会触发rebalance操作)
+spring.kafka.consumer.properties.session.timeout.ms=120000
+# 消费请求超时时间
+spring.kafka.consumer.properties.request.timeout.ms=180000
+# Kafka提供的序列化和反序列化类
+spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer
+spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer
+# 消费端监听的topic不存在时,项目启动会报错(关掉)
+spring.kafka.listener.missing-topics-fatal=false
+# 设置批量消费
+# spring.kafka.listener.type=batch
+# 批量消费每次最多消费多少条消息
+# spring.kafka.consumer.max-poll-records=50
+
+config.connector.activedirectory.providerUrl=ldap://
+config.connector.activedirectory.principal=maxkey
+config.connector.activedirectory.credentials=maxkey
+config.connector.activedirectory.baseDN=dc=maxkey,dc=top
+config.connector.activedirectory.domain=MAXKEY
+config.connector.activedirectory.trustStore=maxkey
+config.connector.activedirectory.trustStore.password=maxkey

+ 36 - 0
maxkey-connectors/maxkey-connector-base/.classpath

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="bin/main" path="src/main/java">
+		<attributes>
+			<attribute name="gradle_scope" value="main"/>
+			<attribute name="gradle_used_by_scope" value="main,test"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="bin/main" path="src/main/resources">
+		<attributes>
+			<attribute name="gradle_scope" value="main"/>
+			<attribute name="gradle_used_by_scope" value="main,test"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="bin/test" path="src/test/java">
+		<attributes>
+			<attribute name="gradle_scope" value="test"/>
+			<attribute name="gradle_used_by_scope" value="test"/>
+			<attribute name="test" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="bin/test" path="src/test/resources">
+		<attributes>
+			<attribute name="gradle_scope" value="test"/>
+			<attribute name="gradle_used_by_scope" value="test"/>
+			<attribute name="test" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
+	<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer">
+		<attributes>
+			<attribute name="org.eclipse.jst.component.nondependency" value=""/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="bin/default"/>
+</classpath>

+ 41 - 0
maxkey-connectors/maxkey-connector-base/.project

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>maxkey-connector-base</name>
+	<comment>Project maxkey-connectors-base created by Buildship.</comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.springframework.ide.eclipse.boot.validation.springbootbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
+		<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
+		<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
+	</natures>
+</projectDescription>

+ 2 - 0
maxkey-connectors/maxkey-connector-base/.settings/org.eclipse.buildship.core.prefs

@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1

+ 2 - 0
maxkey-connectors/maxkey-connector-base/.settings/org.eclipse.core.resources.prefs

@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/<project>=UTF-8

+ 14 - 0
maxkey-connectors/maxkey-connector-base/.settings/org.eclipse.jdt.core.prefs

@@ -0,0 +1,14 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=warning
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.mainOnlyProjectHasTestOnlyDependency=error
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.classpath.outputOverlappingAnotherSource=error
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error

+ 3 - 0
maxkey-connectors/maxkey-connector-base/.settings/org.eclipse.jdt.launching.prefs

@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.launching.PREF_COMPILER_COMPLIANCE_DOES_NOT_MATCH_JRE=warning
+org.eclipse.jdt.launching.PREF_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE=warning

+ 19 - 0
maxkey-connectors/maxkey-connector-base/.settings/org.eclipse.wst.common.component

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-modules id="moduleCoreId" project-version="1.5.0">
+	<wb-module deploy-name="maxkey-connector-base">
+		<wb-resource deploy-path="/" source-path="src/main/resources"/>
+		<wb-resource deploy-path="/" source-path="src/main/java"/>
+		<dependent-module deploy-path="../" handle="module:/resource/maxkey-core/maxkey-core">
+			<dependency-type>uses</dependency-type>
+		</dependent-module>
+		<dependent-module deploy-path="../" handle="module:/resource/maxkey-dao/maxkey-dao">
+			<dependency-type>uses</dependency-type>
+		</dependent-module>
+		<dependent-module deploy-path="../" handle="module:/resource/maxkey-client-sdk/maxkey-client-sdk">
+			<dependency-type>uses</dependency-type>
+		</dependent-module>
+		<dependent-module deploy-path="../" handle="module:/resource/maxkey-identity-kafka/maxkey-identity-kafka">
+			<dependency-type>uses</dependency-type>
+		</dependent-module>
+	</wb-module>
+</project-modules>

+ 6 - 0
maxkey-connectors/maxkey-connector-base/.settings/org.eclipse.wst.common.project.facet.core.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+	<fixed facet="jst.java"/>
+	<installed facet="jst.utility" version="1.0"/>
+	<installed facet="jst.java" version="1.8"/>
+</faceted-project>

+ 2 - 0
maxkey-connectors/maxkey-connector-base/.settings/org.springframework.ide.eclipse.prefs

@@ -0,0 +1,2 @@
+boot.validation.initialized=true
+eclipse.preferences.version=1

+ 16 - 0
maxkey-connectors/maxkey-connector-base/build.gradle

@@ -0,0 +1,16 @@
+description = "maxkey-connector-base"
+
+apply plugin: 'java'
+apply plugin: 'eclipse-wtp'
+
+
+dependencies {
+	//local jars
+	compile fileTree(dir: '../maxkey-lib/*/', include: '*.jar')
+	
+	compile project(":maxkey-core")
+	compile project(":maxkey-dao")
+   	compile project(":maxkey-client-sdk")
+   	compile project(":maxkey-identitys:maxkey-identity-kafka")
+   
+}

+ 53 - 0
maxkey-connectors/maxkey-connector-base/src/main/java/org/maxkey/connector/AbstractConnector.java

@@ -0,0 +1,53 @@
+package org.maxkey.connector;
+
+import java.util.Properties;
+
+import org.springframework.jdbc.core.JdbcTemplate;
+
+
+public abstract class   AbstractConnector<T>{
+	
+	
+	public static class CONNECTOR_TYPE{
+		public static int USERINFO_TYPE=1;
+		public static int ORG_TYPE=2;
+		public static int GROUP_TYPE=3;
+		public static int PASSWORD_TYPE=4;
+	}
+	
+	protected Properties properties;
+	
+	protected JdbcTemplate jdbcTemplate;
+	
+	public boolean create(T entity) throws Exception{
+		return true;
+	}
+	
+	public boolean update(T entity) throws Exception{
+		return true;
+	}
+	
+	public boolean delete(T entity) throws Exception{
+		return true;
+	}
+
+	public Properties getProperties() {
+		return properties;
+	}
+
+	public void setProperties(Properties properties) {
+		this.properties = properties;
+	}
+
+	public JdbcTemplate getJdbcTemplate() {
+		return jdbcTemplate;
+	}
+
+	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
+		this.jdbcTemplate = jdbcTemplate;
+	}
+
+
+	
+	
+}

+ 33 - 0
maxkey-connectors/maxkey-connector-base/src/main/java/org/maxkey/connector/GroupConnector.java

@@ -0,0 +1,33 @@
+package org.maxkey.connector;
+
+import org.maxkey.domain.GroupMember;
+import org.maxkey.domain.Groups;
+
+public abstract class   GroupConnector  extends AbstractConnector <Groups> {
+	
+	@Override
+	public boolean create(Groups group) throws Exception{
+		return true;
+	}
+	
+	@Override
+	public boolean update(Groups group) throws Exception{
+		return true;
+	}
+	
+	@Override
+	public boolean delete(Groups group) throws Exception{
+		return true;
+	}
+	
+
+	public boolean addMember(GroupMember groupMember) throws Exception{
+		return true;
+	}
+	
+
+	public boolean deleteMember(GroupMember groupMember) throws Exception{
+		return true;
+	}
+	
+}

+ 22 - 0
maxkey-connectors/maxkey-connector-base/src/main/java/org/maxkey/connector/OrganizationConnector.java

@@ -0,0 +1,22 @@
+package org.maxkey.connector;
+
+import org.maxkey.domain.Organizations;
+
+public abstract class   OrganizationConnector extends AbstractConnector <Organizations> {
+	
+	@Override
+	public boolean create(Organizations organization) throws Exception{
+		return true;
+	}
+	
+	@Override
+	public boolean update(Organizations organization) throws Exception{
+		return true;
+	}
+	
+	@Override
+	public boolean delete(Organizations organization) throws Exception{
+		return true;
+	}
+	
+}

+ 13 - 0
maxkey-connectors/maxkey-connector-base/src/main/java/org/maxkey/connector/PasswordConnector.java

@@ -0,0 +1,13 @@
+package org.maxkey.connector;
+
+import org.maxkey.domain.UserInfo;
+
+public abstract class   PasswordConnector  extends AbstractConnector<UserInfo> {
+
+	public boolean sync(UserInfo userInfo) throws Exception{
+		return true;
+	}
+	
+
+	
+}

+ 23 - 0
maxkey-connectors/maxkey-connector-base/src/main/java/org/maxkey/connector/UserInfoConnector.java

@@ -0,0 +1,23 @@
+package org.maxkey.connector;
+
+import org.maxkey.domain.UserInfo;
+
+public abstract class   UserInfoConnector  extends AbstractConnector<UserInfo> {
+	
+	@Override
+	public boolean create(UserInfo userInfo)  throws Exception {
+		return true;
+	}
+	
+	@Override
+	public boolean update(UserInfo userInfo) throws Exception{
+		return true;
+	}
+	
+	@Override
+	public boolean delete(UserInfo userInfo) throws Exception{
+		return true;
+	}
+
+	
+}

+ 34 - 0
maxkey-connectors/maxkey-connector-base/src/main/java/org/maxkey/connector/receiver/KafkaGroupsTopicReceiver.java

@@ -0,0 +1,34 @@
+package org.maxkey.connector.receiver;
+
+import java.util.Optional;
+
+import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.maxkey.connector.GroupConnector;
+import org.maxkey.identity.kafka.KafkaIdentityTopic;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.kafka.annotation.KafkaListener;
+import org.springframework.stereotype.Component;
+@Component
+public class KafkaGroupsTopicReceiver {
+    private static final Logger _logger = LoggerFactory.getLogger(KafkaGroupsTopicReceiver.class);
+    
+    @Autowired
+    GroupConnector groupConnector;
+    
+    @KafkaListener(topics = {KafkaIdentityTopic.GROUP_TOPIC})
+    public void listen(ConsumerRecord<?, ?> record) {
+
+        Optional<?> kafkaMessage = Optional.ofNullable(record.value());
+
+        if (kafkaMessage.isPresent()) {
+
+            Object message = kafkaMessage.get();
+
+            _logger.info("----------------- record =" + record);
+            _logger.info("------------------ message =" + message);
+        }
+
+    }
+}

+ 34 - 0
maxkey-connectors/maxkey-connector-base/src/main/java/org/maxkey/connector/receiver/KafkaOrgsTopicReceiver.java

@@ -0,0 +1,34 @@
+package org.maxkey.connector.receiver;
+
+import java.util.Optional;
+
+import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.maxkey.connector.OrganizationConnector;
+import org.maxkey.identity.kafka.KafkaIdentityTopic;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.kafka.annotation.KafkaListener;
+import org.springframework.stereotype.Component;
+@Component
+public class KafkaOrgsTopicReceiver {
+    private static final Logger _logger = LoggerFactory.getLogger(KafkaOrgsTopicReceiver.class);
+   
+    @Autowired
+    OrganizationConnector organizationConnector;
+    
+    @KafkaListener(topics = {KafkaIdentityTopic.ORG_TOPIC})
+    public void listen(ConsumerRecord<?, ?> record) {
+
+        Optional<?> kafkaMessage = Optional.ofNullable(record.value());
+
+        if (kafkaMessage.isPresent()) {
+
+            Object message = kafkaMessage.get();
+
+            _logger.info("----------------- record =" + record);
+            _logger.info("------------------ message =" + message);
+        }
+
+    }
+}

+ 34 - 0
maxkey-connectors/maxkey-connector-base/src/main/java/org/maxkey/connector/receiver/KafkaPasswordTopicReceiver.java

@@ -0,0 +1,34 @@
+package org.maxkey.connector.receiver;
+
+import java.util.Optional;
+
+import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.maxkey.connector.PasswordConnector;
+import org.maxkey.identity.kafka.KafkaIdentityTopic;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.kafka.annotation.KafkaListener;
+import org.springframework.stereotype.Component;
+@Component
+public class KafkaPasswordTopicReceiver {
+    private static final Logger _logger = LoggerFactory.getLogger(KafkaPasswordTopicReceiver.class);
+    
+    @Autowired
+    PasswordConnector passwordConnector;
+    
+    @KafkaListener(topics = {KafkaIdentityTopic.PASSWORD_TOPIC})
+    public void listen(ConsumerRecord<?, ?> record) {
+
+        Optional<?> kafkaMessage = Optional.ofNullable(record.value());
+
+        if (kafkaMessage.isPresent()) {
+
+            Object message = kafkaMessage.get();
+
+            _logger.info("----------------- record =" + record);
+            _logger.info("------------------ message =" + message);
+        }
+
+    }
+}

+ 34 - 0
maxkey-connectors/maxkey-connector-base/src/main/java/org/maxkey/connector/receiver/KafkaUserInfoTopicReceiver.java

@@ -0,0 +1,34 @@
+package org.maxkey.connector.receiver;
+
+import java.util.Optional;
+
+import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.maxkey.connector.UserInfoConnector;
+import org.maxkey.identity.kafka.KafkaIdentityTopic;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.kafka.annotation.KafkaListener;
+import org.springframework.stereotype.Component;
+@Component
+public class KafkaUserInfoTopicReceiver {
+    private static final Logger _logger = LoggerFactory.getLogger(KafkaUserInfoTopicReceiver.class);
+    
+    @Autowired
+    UserInfoConnector userInfoConnector;
+    
+    @KafkaListener(topics = {KafkaIdentityTopic.USERINFO_TOPIC})
+    public void listen(ConsumerRecord<?, ?> record) {
+
+        Optional<?> kafkaMessage = Optional.ofNullable(record.value());
+
+        if (kafkaMessage.isPresent()) {
+
+            Object message = kafkaMessage.get();
+
+            _logger.info("----------------- record =" + record);
+            _logger.info("------------------ message =" + message);
+        }
+
+    }
+}

+ 36 - 0
maxkey-connectors/maxkey-connector-ldap/.classpath

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="bin/main" path="src/main/java">
+		<attributes>
+			<attribute name="gradle_scope" value="main"/>
+			<attribute name="gradle_used_by_scope" value="main,test"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="bin/main" path="src/main/resources">
+		<attributes>
+			<attribute name="gradle_scope" value="main"/>
+			<attribute name="gradle_used_by_scope" value="main,test"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="bin/test" path="src/test/java">
+		<attributes>
+			<attribute name="gradle_scope" value="test"/>
+			<attribute name="gradle_used_by_scope" value="test"/>
+			<attribute name="test" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="bin/test" path="src/test/resources">
+		<attributes>
+			<attribute name="gradle_scope" value="test"/>
+			<attribute name="gradle_used_by_scope" value="test"/>
+			<attribute name="test" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
+	<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer">
+		<attributes>
+			<attribute name="org.eclipse.jst.component.nondependency" value=""/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="bin/default"/>
+</classpath>

+ 41 - 0
maxkey-connectors/maxkey-connector-ldap/.project

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>maxkey-connector-ldap</name>
+	<comment>Project maxkey-connectors-ldap created by Buildship.</comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.springframework.ide.eclipse.boot.validation.springbootbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
+		<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
+		<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
+	</natures>
+</projectDescription>

+ 2 - 0
maxkey-connectors/maxkey-connector-ldap/.settings/org.eclipse.buildship.core.prefs

@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1

+ 2 - 0
maxkey-connectors/maxkey-connector-ldap/.settings/org.eclipse.core.resources.prefs

@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/<project>=UTF-8

+ 14 - 0
maxkey-connectors/maxkey-connector-ldap/.settings/org.eclipse.jdt.core.prefs

@@ -0,0 +1,14 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=warning
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.mainOnlyProjectHasTestOnlyDependency=error
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.classpath.outputOverlappingAnotherSource=error
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error

+ 3 - 0
maxkey-connectors/maxkey-connector-ldap/.settings/org.eclipse.jdt.launching.prefs

@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.launching.PREF_COMPILER_COMPLIANCE_DOES_NOT_MATCH_JRE=warning
+org.eclipse.jdt.launching.PREF_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE=warning

+ 22 - 0
maxkey-connectors/maxkey-connector-ldap/.settings/org.eclipse.wst.common.component

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-modules id="moduleCoreId" project-version="1.5.0">
+	<wb-module deploy-name="maxkey-connector-ldap">
+		<wb-resource deploy-path="/" source-path="src/main/resources"/>
+		<wb-resource deploy-path="/" source-path="src/main/java"/>
+		<dependent-module deploy-path="../" handle="module:/resource/maxkey-core/maxkey-core">
+			<dependency-type>uses</dependency-type>
+		</dependent-module>
+		<dependent-module deploy-path="../" handle="module:/resource/maxkey-dao/maxkey-dao">
+			<dependency-type>uses</dependency-type>
+		</dependent-module>
+		<dependent-module deploy-path="../" handle="module:/resource/maxkey-client-sdk/maxkey-client-sdk">
+			<dependency-type>uses</dependency-type>
+		</dependent-module>
+		<dependent-module deploy-path="../" handle="module:/resource/maxkey-connector-base/maxkey-connector-base">
+			<dependency-type>uses</dependency-type>
+		</dependent-module>
+		<dependent-module deploy-path="../" handle="module:/resource/maxkey-identity-kafka/maxkey-identity-kafka">
+			<dependency-type>uses</dependency-type>
+		</dependent-module>
+	</wb-module>
+</project-modules>

+ 6 - 0
maxkey-connectors/maxkey-connector-ldap/.settings/org.eclipse.wst.common.project.facet.core.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+	<fixed facet="jst.java"/>
+	<installed facet="jst.utility" version="1.0"/>
+	<installed facet="jst.java" version="1.8"/>
+</faceted-project>

+ 2 - 0
maxkey-connectors/maxkey-connector-ldap/.settings/org.springframework.ide.eclipse.prefs

@@ -0,0 +1,2 @@
+boot.validation.initialized=true
+eclipse.preferences.version=1

+ 17 - 0
maxkey-connectors/maxkey-connector-ldap/build.gradle

@@ -0,0 +1,17 @@
+description = "maxkey-connector-ldap"
+
+apply plugin: 'java'
+apply plugin: 'eclipse-wtp'
+
+
+dependencies {
+	//local jars
+	compile fileTree(dir: '../maxkey-lib/*/', include: '*.jar')
+	
+	compile project(":maxkey-core")
+	compile project(":maxkey-dao")
+   	compile project(":maxkey-client-sdk")
+   	compile project(":maxkey-connectors:maxkey-connector-base")
+   	compile project(":maxkey-identitys:maxkey-identity-kafka")
+   
+}

+ 55 - 0
maxkey-connectors/maxkey-connector-ldap/src/main/java/org/maxkey/connector/LdapConsumerApplication.java

@@ -0,0 +1,55 @@
+package org.maxkey.connector;
+
+import org.maxkey.constants.ConstantsProperties;
+import org.maxkey.persistence.ldap.LdapUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+
+@Configuration
+@PropertySource(ConstantsProperties.applicationPropertySource)
+@SpringBootApplication
+@ComponentScan(basePackages = {
+        "org.maxkey.connector",
+        "org.maxkey.connector.receiver",
+        "org.maxkey.connector.ldap"
+    })
+public class LdapConsumerApplication {
+
+	public static void main(String[] args) {
+		// TODO Auto-generated method stub
+	    ConfigurableApplicationContext context = SpringApplication.run(LdapConsumerApplication.class, args);
+		
+	}
+	
+	//@Bean(name = "ldapUtils")
+	public LdapUtils getLdapConnection(
+			@Value("${config.connector.ldap.providerUrl}") String providerUrl,
+			@Value("${config.connector.ldap.principal}") String principal,
+			@Value("${config.connector.ldap.credentials}") String credentials,
+			@Value("${config.connector.ldap.baseDN}") String baseDn
+			)throws Exception{
+		
+		LdapUtils ldapUtils=new LdapUtils(
+				providerUrl,
+				principal,
+				credentials,
+				baseDn);
+		if(ldapUtils.openConnection()==null){
+			 throw new Exception("connection to Ldap Error.");   
+		}
+		return ldapUtils;
+	}
+	
+	
+	   protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+	        return application.sources(LdapConsumerApplication.class);
+	    }
+
+}

+ 153 - 0
maxkey-connectors/maxkey-connector-ldap/src/main/java/org/maxkey/connector/ldap/Group2Ldap.java

@@ -0,0 +1,153 @@
+package org.maxkey.connector.ldap;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.ModificationItem;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+
+import org.maxkey.connector.GroupConnector;
+import org.maxkey.domain.GroupMember;
+import org.maxkey.domain.Groups;
+import org.maxkey.persistence.ldap.LdapUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+@Component(value = "groupConnector")
+public class Group2Ldap extends GroupConnector {
+	private final static Logger logger = LoggerFactory.getLogger(Group2Ldap.class);
+
+	LdapUtils  ldapUtils;
+	public Group2Ldap() {
+
+	}
+
+	@Override
+	public boolean create(Groups group)  throws Exception{
+		logger.info("create");
+		try {
+			Attributes attributes = new BasicAttributes();
+			attributes.put(new BasicAttribute("objectClass","groupOfUniqueNames"));
+			attributes.put(new BasicAttribute("cn",group.getName()));
+			attributes.put(new BasicAttribute("uniqueMember","uid=dummy"));
+			
+			String dn="cn="+group.getName()+",dc=groups,"+ldapUtils.getBaseDN();
+		
+			ldapUtils.getCtx().createSubcontext(dn, attributes);
+			ldapUtils.close();
+		} catch (NamingException e) {
+			e.printStackTrace();
+		}
+		return true;
+	}
+
+	@Override
+	public boolean update(Groups group)  throws Exception{
+		logger.info("update");
+		try {
+			SearchControls constraints = new SearchControls();
+			constraints.setSearchScope(ldapUtils.getSearchScope());
+			NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
+					.search(ldapUtils.getBaseDN(), "(cn="+group.getName()+")", constraints);
+			String oldDn="";
+			String rdn="";
+			if (results == null || !results.hasMore()) {
+				return create(group);
+			}else{
+				SearchResult sr = (SearchResult) results.next();
+				oldDn =sr.getNameInNamespace();
+				String[] dnSplit=oldDn.split(",");
+				rdn=oldDn.substring(oldDn.indexOf(","), oldDn.length());
+				
+				String groupName=dnSplit[0].split("=")[1];
+				if(group.getName()!=groupName){
+					String newDn="cn="+group.getName()+","+rdn;
+					ldapUtils.getCtx().rename(oldDn, newDn);
+					ModificationItem[] modificationItems = new ModificationItem[1];
+					modificationItems[0]=new ModificationItem(DirContext.REMOVE_ATTRIBUTE,new BasicAttribute("cn",groupName));
+					ldapUtils.getCtx().modifyAttributes(newDn, modificationItems);
+				}
+			}
+			
+			ldapUtils.close();
+		} catch (NamingException e) {
+			e.printStackTrace();
+		}
+		return true;
+	}
+
+	@Override
+	public boolean delete(Groups group) throws Exception {
+		logger.info("delete");
+		try {
+			String dn="cn="+group.getName()+",dc=groups,"+ldapUtils.getBaseDN();
+			ldapUtils.getCtx().destroySubcontext(dn);
+			ldapUtils.close();
+		} catch (NamingException e) {
+			e.printStackTrace();
+		}
+		return true;
+	}
+
+	@Override
+	public boolean addMember(GroupMember groupMember) throws Exception {
+		try {
+			SearchControls constraints = new SearchControls();
+			constraints.setSearchScope(ldapUtils.getSearchScope());
+			NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
+					.search(ldapUtils.getBaseDN(), "(cn="+groupMember.getGroupName()+")", constraints);
+			if (results == null || !results.hasMore()) {
+				Groups  group =new Groups();
+				group.setName(groupMember.getGroupName());
+				create(group);
+			}
+			
+			String uniqueMember="uid="+groupMember.getMemberName()+",dc=users,"+ldapUtils.getBaseDN();
+			ModificationItem[] modificationItems = new ModificationItem[1];
+			modificationItems[0]=new ModificationItem(DirContext.ADD_ATTRIBUTE,new BasicAttribute("uniqueMember",uniqueMember));
+			
+			String dn="cn="+groupMember.getGroupName()+",dc=groups,"+ldapUtils.getBaseDN();
+			logger.debug("dn : "+dn);
+			logger.debug("uniqueMember : "+uniqueMember);
+			ldapUtils.getCtx().modifyAttributes(dn, modificationItems);
+			ldapUtils.close();
+		} catch (NamingException e) {
+			e.printStackTrace();
+		}
+		return true;
+	}
+
+	@Override
+	public boolean deleteMember(GroupMember groupMember)  throws Exception{
+		try {
+			SearchControls constraints = new SearchControls();
+			constraints.setSearchScope(ldapUtils.getSearchScope());
+			NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
+					.search(ldapUtils.getBaseDN(), "(cn="+groupMember.getGroupName()+")", constraints);
+			if (results == null || !results.hasMore()) {
+				return true;
+			}
+			
+			String uniqueMember="uid="+groupMember.getMemberName()+",dc=users,"+ldapUtils.getBaseDN();
+			ModificationItem[] modificationItems = new ModificationItem[1];
+			modificationItems[0]=new ModificationItem(DirContext.REMOVE_ATTRIBUTE,new BasicAttribute("uniqueMember",uniqueMember));
+			
+			String dn="cn="+groupMember.getGroupName()+",dc=groups,"+ldapUtils.getBaseDN();
+			logger.debug("dn : "+dn);
+			logger.debug("uniqueMember : "+uniqueMember);
+			ldapUtils.getCtx().modifyAttributes(dn, modificationItems);
+			ldapUtils.close();
+		} catch (NamingException e) {
+			e.printStackTrace();
+		}
+		return true;
+	}
+	
+
+
+}

+ 119 - 0
maxkey-connectors/maxkey-connector-ldap/src/main/java/org/maxkey/connector/ldap/Organization2Ldap.java

@@ -0,0 +1,119 @@
+package org.maxkey.connector.ldap;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.ModificationItem;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+
+import org.maxkey.connector.OrganizationConnector;
+import org.maxkey.domain.Organizations;
+import org.maxkey.persistence.ldap.LdapUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+@Component(value = "organizationConnector")
+public class Organization2Ldap  extends OrganizationConnector{
+	private final static Logger logger = LoggerFactory.getLogger(Organization2Ldap.class);
+
+	LdapUtils  ldapUtils;
+	public Organization2Ldap() {
+		
+	}
+
+	@Override
+	public boolean create(Organizations organization) throws Exception {
+		logger.info("create");
+			SearchControls constraints = new SearchControls();
+			constraints.setSearchScope(ldapUtils.getSearchScope());
+			NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
+					.search(ldapUtils.getBaseDN(), "(&(objectClass=organizationalUnit)(description="+organization.getpId()+"))", constraints);
+			String rdn="";
+			if (results == null || !results.hasMore()) {
+				rdn=ldapUtils.getBaseDN();
+			}else{
+				SearchResult sr = (SearchResult) results.next();
+				rdn =sr.getNameInNamespace();
+			}
+			
+			Attributes attributes = new BasicAttributes();
+			attributes.put(new BasicAttribute("objectClass","organizationalUnit"));
+			attributes.put(new BasicAttribute("ou",organization.getName()));
+			//attributes.put(new BasicAttribute("name",organization.getName()));
+			//attributes.put(new BasicAttribute("id",organization.getId()));
+			//attributes.put(new BasicAttribute("porgname",organization.getpName()));
+			//attributes.put(new BasicAttribute("porgid",organization.getpId()));
+			attributes.put(new BasicAttribute("description",organization.getId()));
+			
+			String dn="ou="+organization.getName()+","+rdn;
+			
+			ldapUtils.getCtx().createSubcontext(dn, attributes);
+			ldapUtils.close();
+			
+		return super.create(organization);
+	}
+
+	@Override
+	public boolean update(Organizations organization)  throws Exception{
+		logger.info("update");
+			SearchControls constraints = new SearchControls();
+			constraints.setSearchScope(ldapUtils.getSearchScope());
+			NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
+					.search(ldapUtils.getBaseDN(), "(&(objectClass=organizationalUnit)(description="+organization.getId()+"))", constraints);
+			String oldDn="";
+			String rdn="";
+			if (results == null || !results.hasMore()) {
+				return create(organization);
+			}else{
+				SearchResult sr = (SearchResult) results.next();
+				oldDn =sr.getNameInNamespace();
+				String[] dnSplit=oldDn.split(",");
+				rdn=oldDn.substring(oldDn.indexOf(",")+1, oldDn.length());
+				
+				String ouName=dnSplit[0].split("=")[1];
+				if(organization.getName()!=ouName){
+					String newDn="ou="+organization.getName()+","+rdn;
+					logger.debug("oldDn : "+oldDn);
+					logger.debug("newDn : "+newDn);
+					ldapUtils.getCtx().rename(oldDn, newDn);
+					ModificationItem[] modificationItems = new ModificationItem[1];
+					modificationItems[0]=new ModificationItem(DirContext.REMOVE_ATTRIBUTE,new BasicAttribute("ou",ouName));
+					//modificationItems[1]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("name",organization.getName()));
+					//modificationItems[2]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("id",organization.getId()));
+					//modificationItems[3]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("porgname",organization.getpName()));
+					//modificationItems[4]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("porgid",organization.getpId()));
+					ldapUtils.getCtx().modifyAttributes(newDn, modificationItems);
+				}
+			}
+			
+			ldapUtils.close();
+		
+		return super.update(organization);
+	}
+
+	@Override
+	public boolean delete(Organizations organization)  throws Exception{
+		logger.info("delete");
+			SearchControls constraints = new SearchControls();
+			constraints.setSearchScope(ldapUtils.getSearchScope());
+			NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
+					.search(ldapUtils.getBaseDN(), "(&(objectClass=organizationalUnit)(description="+organization.getId()+"))", constraints);
+			String dn="";
+			if (results == null || !results.hasMore()) {
+				
+			}else{
+				SearchResult sr = (SearchResult) results.next();
+				dn =sr.getNameInNamespace();
+				ldapUtils.getCtx().destroySubcontext(dn);
+			}
+			
+			ldapUtils.close();
+		
+		return super.delete(organization);
+	}
+
+}

+ 45 - 0
maxkey-connectors/maxkey-connector-ldap/src/main/java/org/maxkey/connector/ldap/Password2Ldap.java

@@ -0,0 +1,45 @@
+package org.maxkey.connector.ldap;
+
+import javax.naming.NamingException;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.ModificationItem;
+
+import org.maxkey.connector.PasswordConnector;
+import org.maxkey.crypto.ReciprocalUtils;
+import org.maxkey.domain.UserInfo;
+import org.maxkey.persistence.ldap.LdapUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+
+@Component(value = "passwordConnector")
+public class Password2Ldap  extends PasswordConnector{
+	private final static Logger logger = LoggerFactory.getLogger(Password2Ldap.class);
+
+	LdapUtils  ldapUtils;
+	
+	public Password2Ldap() {
+		
+	}
+
+	@Override
+	public boolean sync(UserInfo userInfo) throws Exception{
+		logger.info("changePassword");
+		try {
+			ModificationItem[] modificationItems = new ModificationItem[1];
+			modificationItems[0]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("userPassword",ReciprocalUtils.decoder(userInfo.getDecipherable())));
+			
+			String dn="uid="+userInfo.getUsername()+",dc=users,"+ldapUtils.getBaseDN();
+			
+			ldapUtils.getCtx().modifyAttributes(dn, modificationItems);
+			ldapUtils.close();
+		} catch (NamingException e) {
+			e.printStackTrace();
+		}
+		return true;
+	}
+	
+	
+}

+ 140 - 0
maxkey-connectors/maxkey-connector-ldap/src/main/java/org/maxkey/connector/ldap/UserInfo2Ldap.java

@@ -0,0 +1,140 @@
+package org.maxkey.connector.ldap;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.ModificationItem;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+
+import org.maxkey.connector.UserInfoConnector;
+import org.maxkey.crypto.ReciprocalUtils;
+import org.maxkey.domain.UserInfo;
+import org.maxkey.persistence.ldap.LdapUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+@Component(value = "userInfoConnector")
+public class UserInfo2Ldap  extends UserInfoConnector{
+	private final static Logger logger = LoggerFactory.getLogger(UserInfo2Ldap.class);
+
+	LdapUtils  ldapUtils;
+	
+	public UserInfo2Ldap() {
+		
+	}
+
+	@Override
+	public boolean create(UserInfo userInfo) throws Exception{
+		logger.info("create");
+		try {
+			Attributes attributes = new BasicAttributes();
+			attributes.put(new BasicAttribute("objectClass","inetOrgPerson"));
+			attributes.put(new BasicAttribute("uid",userInfo.getUsername()));
+			attributes.put(new BasicAttribute("userPassword",ReciprocalUtils.decoder(userInfo.getDecipherable())));
+			attributes.put(new BasicAttribute("displayName",userInfo.getDisplayName()));
+			attributes.put(new BasicAttribute("cn",userInfo.getDisplayName()));
+			attributes.put(new BasicAttribute("givenName",userInfo.getGivenName()));
+			attributes.put(new BasicAttribute("sn",userInfo.getFamilyName()));
+
+			attributes.put(new BasicAttribute("mobile",userInfo.getWorkPhoneNumber()==null?"":userInfo.getWorkPhoneNumber()));
+			attributes.put(new BasicAttribute("mail",userInfo.getWorkEmail()==null?"":userInfo.getWorkEmail()));
+		
+			attributes.put(new BasicAttribute("employeeNumber",userInfo.getEmployeeNumber()==null?"":userInfo.getEmployeeNumber()));
+			attributes.put(new BasicAttribute("ou",userInfo.getDepartment()==null?"":userInfo.getDepartment()));
+			String managerDn="uid=dummy";
+			if(userInfo.getManagerId()==null||userInfo.getManagerId().equals("")){
+
+			}else{
+				UserInfo queryManager=new UserInfo();
+				queryManager.setId(userInfo.getManagerId());
+				UserInfo manager=loadUser(queryManager);
+				managerDn="uid="+manager.getUsername()+",dc=users,"+ldapUtils.getBaseDN();
+			}
+			attributes.put(new BasicAttribute("manager",managerDn));
+			attributes.put(new BasicAttribute("departmentNumber",userInfo.getDepartmentId()==null?"":userInfo.getDepartmentId()));
+			attributes.put(new BasicAttribute("title",userInfo.getJobTitle()==null?"":userInfo.getJobTitle()));
+			
+			
+			String dn="uid="+userInfo.getUsername()+",dc=users,"+ldapUtils.getBaseDN();
+		
+			ldapUtils.getCtx().createSubcontext(dn, attributes);
+			ldapUtils.close();
+			super.create(userInfo);
+		} catch (NamingException e) {
+			e.printStackTrace();
+		}
+		return true;
+	}
+	
+	@Override
+	public boolean update(UserInfo userInfo) throws Exception{
+		logger.info("update");
+		try {
+			SearchControls constraints = new SearchControls();
+			constraints.setSearchScope(ldapUtils.getSearchScope());
+			NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
+					.search(ldapUtils.getBaseDN(), "(&(objectClass=inetOrgPerson)(uid="+userInfo.getUsername()+"))", constraints);
+			if (results == null || !results.hasMore()) {
+				return create(loadUser(userInfo));
+			}
+			
+			ModificationItem[] modificationItems = new ModificationItem[10];
+			modificationItems[0]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("displayName",userInfo.getDisplayName()));
+			modificationItems[1]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("cn",userInfo.getDisplayName()));
+			modificationItems[2]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("givenName",userInfo.getGivenName()));
+			modificationItems[3]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("sn",userInfo.getFamilyName()));
+			
+			modificationItems[4]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("mobile",userInfo.getWorkPhoneNumber()==null?"":userInfo.getWorkPhoneNumber()));
+			modificationItems[5]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("mail",userInfo.getWorkEmail()==null?"":userInfo.getWorkEmail()));
+			
+			modificationItems[6]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("employeeNumber",userInfo.getEmployeeNumber()==null?"":userInfo.getEmployeeNumber()));
+			modificationItems[7]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("ou",userInfo.getDepartment()==null?"":userInfo.getDepartment()));
+			modificationItems[8]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("departmentNumber",userInfo.getDepartmentId()==null?"":userInfo.getDepartmentId()));
+			modificationItems[9]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("title",userInfo.getJobTitle()==null?"":userInfo.getJobTitle()));
+			
+			String managerDn="uid=dummy";
+			if(userInfo.getManagerId()==null||userInfo.getManagerId().equals("")){
+
+			}else{
+				UserInfo queryManager=new UserInfo();
+				queryManager.setId(userInfo.getManagerId());
+				UserInfo manager=loadUser(queryManager);
+				managerDn="uid="+manager.getUsername()+",dc=users,"+ldapUtils.getBaseDN();
+			}
+			modificationItems[9]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("manager",managerDn));
+
+			
+			
+			String dn="uid="+userInfo.getUsername()+",dc=users,"+ldapUtils.getBaseDN();
+			
+			ldapUtils.getCtx().modifyAttributes(dn, modificationItems);
+			ldapUtils.close();
+		} catch (NamingException e) {
+			e.printStackTrace();
+		}
+		return true;
+		
+	}
+	
+	@Override
+	public boolean delete(UserInfo userInfo) throws Exception{
+		logger.info("delete");
+		try {
+			String dn="uid="+userInfo.getUsername()+",dc=users,"+ldapUtils.getBaseDN();
+			ldapUtils.getCtx().destroySubcontext(dn);
+			ldapUtils.close();
+			super.delete(userInfo);
+		} catch (NamingException e) {
+			e.printStackTrace();
+		}
+		return true;
+	}
+
+	public UserInfo loadUser(UserInfo UserInfo) {
+		return null;
+	}
+}

+ 47 - 0
maxkey-connectors/maxkey-connector-ldap/src/main/resources/application.properties

@@ -0,0 +1,47 @@
+#spring.profiles.active=dev
+#application
+application.title=MaxKey-Connector-LDAP
+application.name=MaxKey-Connector-LDAP
+application.formatted-version=v2.0.0 GA
+
+#server port
+server.port=9601
+
+#datasource
+spring.datasource.username=root
+spring.datasource.password=maxkey
+spring.datasource.url=jdbc:mysql://localhost/maxkey?autoReconnect=true&characterEncoding=UTF-8
+spring.datasource.driver-class-name=com.mysql.jdbc.Driver
+spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
+
+spring.kafka.bootstrap-servers=localhost:9092
+###########【初始化消费者配置】###########
+# 默认的消费组ID
+spring.kafka.consumer.properties.group.id=test-consumer-group
+# 是否自动提交offset
+spring.kafka.consumer.enable-auto-commit=true
+# 提交offset延时(接收到消息后多久提交offset)
+spring.kafka.consumer.auto.commit.interval.ms=1000
+# 当kafka中没有初始offset或offset超出范围时将自动重置offset
+# earliest:重置为分区中最小的offset;
+# latest:重置为分区中最新的offset(消费分区中新产生的数据);
+# none:只要有一个分区不存在已提交的offset,就抛出异常;
+spring.kafka.consumer.auto-offset-reset=latest
+# 消费会话超时时间(超过这个时间consumer没有发送心跳,就会触发rebalance操作)
+spring.kafka.consumer.properties.session.timeout.ms=120000
+# 消费请求超时时间
+spring.kafka.consumer.properties.request.timeout.ms=180000
+# Kafka提供的序列化和反序列化类
+spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer
+spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer
+# 消费端监听的topic不存在时,项目启动会报错(关掉)
+spring.kafka.listener.missing-topics-fatal=false
+# 设置批量消费
+# spring.kafka.listener.type=batch
+# 批量消费每次最多消费多少条消息
+# spring.kafka.consumer.max-poll-records=50
+
+config.connector.ldap.providerUrl=ldap://
+config.connector.ldap.principal=maxkey
+config.connector.ldap.credentials=maxkey
+config.connector.ldap.baseDN=dc=maxkey,dc=top

+ 11 - 0
maxkey-core/src/main/java/org/maxkey/config/ApplicationConfig.java

@@ -52,6 +52,9 @@ public class ApplicationConfig {
     @Value("${server.port:8080}")
     private int port;
 
+    @Value("${config.identity.kafkasupport:false}")
+    private boolean kafkaSupport;
+    
     public int getPort() {
         return port;
     }
@@ -198,6 +201,14 @@ public class ApplicationConfig {
         this.defaultUri = defaultUri;
     }
 
+    public boolean isKafkaSupport() {
+        return kafkaSupport;
+    }
+
+    public void setKafkaSupport(boolean kafkaSupport) {
+        this.kafkaSupport = kafkaSupport;
+    }
+
     /*
      * public boolean isWhiteList() { return whiteList; }
      * 

+ 13 - 0
maxkey-dao/.settings/org.eclipse.jdt.core.prefs

@@ -1,4 +1,17 @@
 eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=warning
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.mainOnlyProjectHasTestOnlyDependency=error
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.classpath.outputOverlappingAnotherSource=error
 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
 org.eclipse.jdt.core.compiler.source=1.8
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error

+ 1 - 1
maxkey-dao/build.gradle

@@ -5,5 +5,5 @@ dependencies {
 	compile fileTree(dir: '../maxkey-lib/*/', include: '*.jar')
     	
     compile project(":maxkey-core")
-    
+    compile project(":maxkey-identitys:maxkey-identity-kafka")
 }

+ 34 - 0
maxkey-dao/src/main/java/org/maxkey/dao/service/OrganizationsService.java

@@ -3,11 +3,18 @@ package org.maxkey.dao.service;
 import org.apache.mybatis.jpa.persistence.JpaBaseService;
 import org.maxkey.dao.persistence.OrganizationsMapper;
 import org.maxkey.domain.Organizations;
+import org.maxkey.identity.kafka.KafkaIdentityAction;
+import org.maxkey.identity.kafka.KafkaIdentityTopic;
+import org.maxkey.identity.kafka.KafkaProvisioningService;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 @Service
 public class OrganizationsService  extends JpaBaseService<Organizations>{
 
+    @Autowired
+    KafkaProvisioningService kafkaProvisioningService;
+    
 	public OrganizationsService() {
 		super(OrganizationsMapper.class);
 	}
@@ -21,4 +28,31 @@ public class OrganizationsService  extends JpaBaseService<Organizations>{
 		return (OrganizationsMapper)super.getMapper();
 	}
 	
+	 public boolean insert(Organizations organization) {
+	     if(super.insert(organization)){
+             kafkaProvisioningService.send(
+                     KafkaIdentityTopic.ORG_TOPIC, organization, KafkaIdentityAction.CREATE_ACTION);
+             return true;
+         }
+         return false;
+	 }
+	 
+	 public boolean update(Organizations organization) {
+	     if(super.update(organization)){
+             kafkaProvisioningService.send(
+                     KafkaIdentityTopic.ORG_TOPIC, organization, KafkaIdentityAction.UPDATE_ACTION);
+             return true;
+         }
+         return false;
+     }
+ 
+	 public boolean delete(Organizations organization) {
+	     if(super.delete(organization)){
+             kafkaProvisioningService.send(
+                     KafkaIdentityTopic.ORG_TOPIC, organization, KafkaIdentityAction.DELETE_ACTION);
+             return true;
+         }
+         return false;
+	 }
+	
 }

+ 17 - 5
maxkey-dao/src/main/java/org/maxkey/dao/service/UserInfoService.java

@@ -8,6 +8,9 @@ import org.maxkey.crypto.password.PasswordReciprocal;
 import org.maxkey.dao.persistence.UserInfoMapper;
 import org.maxkey.domain.ChangePassword;
 import org.maxkey.domain.UserInfo;
+import org.maxkey.identity.kafka.KafkaIdentityAction;
+import org.maxkey.identity.kafka.KafkaIdentityTopic;
+import org.maxkey.identity.kafka.KafkaProvisioningService;
 import org.maxkey.util.DateUtils;
 import org.maxkey.util.StringUtils;
 import org.maxkey.web.WebContext;
@@ -29,6 +32,8 @@ public class UserInfoService extends JpaBaseService<UserInfo> {
 	@Autowired
 	private PasswordEncoder passwordEncoder;
 	
+	@Autowired
+	KafkaProvisioningService kafkaProvisioningService;
 	
 	public UserInfoService() {
 		super(UserInfoMapper.class);
@@ -46,22 +51,27 @@ public class UserInfoService extends JpaBaseService<UserInfo> {
     public boolean insert(UserInfo userInfo) {
         userInfo = passwordEncoder(userInfo);
         if (super.insert(userInfo)) {
-
+            kafkaProvisioningService.send(
+                    KafkaIdentityTopic.USERINFO_TOPIC, userInfo, KafkaIdentityAction.CREATE_ACTION);
             return true;
         }
 
         return false;
     }
 	
-	public boolean update(UserInfo userinfo) {
-		 if(super.update(userinfo)){
+	public boolean update(UserInfo userInfo) {
+		 if(super.update(userInfo)){
+		     kafkaProvisioningService.send(
+		             KafkaIdentityTopic.USERINFO_TOPIC, userInfo, KafkaIdentityAction.UPDATE_ACTION);
 			 return true;
 		 }
 		 return false;
 	}
 	
-	public boolean delete(UserInfo userinfo) {
-		if( super.delete(userinfo)){
+	public boolean delete(UserInfo userInfo) {
+		if( super.delete(userInfo)){
+		    kafkaProvisioningService.send(
+		            KafkaIdentityTopic.USERINFO_TOPIC, userInfo, KafkaIdentityAction.DELETE_ACTION);
 			 return true;
 		}
 		return false;
@@ -130,6 +140,8 @@ public class UserInfoService extends JpaBaseService<UserInfo> {
 				changePassword.setUsername(userInfo.getUsername());
 				changePassword.setDecipherable(userInfo.getDecipherable());
 				changePassword.setPassword(userInfo.getPassword());
+				kafkaProvisioningService.send(
+				        KafkaIdentityTopic.PASSWORD_TOPIC, changePassword, KafkaIdentityAction.PASSWORD_ACTION);
 				return true;
 			}
 			return false;

+ 5 - 0
maxkey-identitys/.project

@@ -15,6 +15,11 @@
 			<arguments>
 			</arguments>
 		</buildCommand>
+		<buildCommand>
+			<name>org.springframework.ide.eclipse.boot.validation.springbootbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 	</buildSpec>
 	<natures>
 		<nature>org.eclipse.jdt.core.javanature</nature>

+ 36 - 0
maxkey-identitys/maxkey-identity-kafka/.classpath

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="bin/main" path="src/main/java">
+		<attributes>
+			<attribute name="gradle_scope" value="main"/>
+			<attribute name="gradle_used_by_scope" value="main,test"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="bin/main" path="src/main/resources">
+		<attributes>
+			<attribute name="gradle_scope" value="main"/>
+			<attribute name="gradle_used_by_scope" value="main,test"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="bin/test" path="src/test/java">
+		<attributes>
+			<attribute name="gradle_scope" value="test"/>
+			<attribute name="gradle_used_by_scope" value="test"/>
+			<attribute name="test" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="bin/test" path="src/test/resources">
+		<attributes>
+			<attribute name="gradle_scope" value="test"/>
+			<attribute name="gradle_used_by_scope" value="test"/>
+			<attribute name="test" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
+	<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer">
+		<attributes>
+			<attribute name="org.eclipse.jst.component.nondependency" value=""/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="bin/default"/>
+</classpath>

+ 41 - 0
maxkey-identitys/maxkey-identity-kafka/.project

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>maxkey-identity-kafka</name>
+	<comment>Project maxkey-identity-kafka created by Buildship.</comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.springframework.ide.eclipse.boot.validation.springbootbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
+		<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
+		<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
+	</natures>
+</projectDescription>

+ 2 - 0
maxkey-identitys/maxkey-identity-kafka/.settings/org.eclipse.buildship.core.prefs

@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1

+ 2 - 0
maxkey-identitys/maxkey-identity-kafka/.settings/org.eclipse.core.resources.prefs

@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/<project>=UTF-8

+ 116 - 0
maxkey-identitys/maxkey-identity-kafka/.settings/org.eclipse.jdt.core.prefs

@@ -0,0 +1,116 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=warning
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.mainOnlyProjectHasTestOnlyDependency=error
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.classpath.outputOverlappingAnotherSource=error
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.APILeak=warning
+org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
+org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error

+ 3 - 0
maxkey-identitys/maxkey-identity-kafka/.settings/org.eclipse.jdt.launching.prefs

@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.launching.PREF_COMPILER_COMPLIANCE_DOES_NOT_MATCH_JRE=warning
+org.eclipse.jdt.launching.PREF_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE=warning

+ 16 - 0
maxkey-identitys/maxkey-identity-kafka/.settings/org.eclipse.wst.common.component

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-modules id="moduleCoreId" project-version="1.5.0">
+	<wb-module deploy-name="maxkey-identity-kafka">
+		<wb-resource deploy-path="/" source-path="src/main/resources"/>
+		<wb-resource deploy-path="/" source-path="src/main/java"/>
+		<dependent-module deploy-path="../" handle="module:/resource/maxkey-core/maxkey-core">
+			<dependency-type>uses</dependency-type>
+		</dependent-module>
+		<dependent-module deploy-path="../" handle="module:/resource/maxkey-dao/maxkey-dao">
+			<dependency-type>uses</dependency-type>
+		</dependent-module>
+		<dependent-module deploy-path="../" handle="module:/resource/maxkey-client-sdk/maxkey-client-sdk">
+			<dependency-type>uses</dependency-type>
+		</dependent-module>
+	</wb-module>
+</project-modules>

+ 6 - 0
maxkey-identitys/maxkey-identity-kafka/.settings/org.eclipse.wst.common.project.facet.core.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+	<fixed facet="jst.java"/>
+	<installed facet="jst.utility" version="1.0"/>
+	<installed facet="jst.java" version="1.8"/>
+</faceted-project>

+ 2 - 0
maxkey-identitys/maxkey-identity-kafka/.settings/org.springframework.ide.eclipse.prefs

@@ -0,0 +1,2 @@
+boot.validation.initialized=true
+eclipse.preferences.version=1

+ 15 - 0
maxkey-identitys/maxkey-identity-kafka/build.gradle

@@ -0,0 +1,15 @@
+description = "maxkey-identity-kafka"
+
+apply plugin: 'java'
+apply plugin: 'eclipse-wtp'
+
+
+dependencies {
+	//local jars
+	compile fileTree(dir: '../maxkey-lib/*/', include: '*.jar')
+	
+	compile project(":maxkey-core")
+	compile project(":maxkey-dao")
+   	compile project(":maxkey-client-sdk")
+   
+}

+ 10 - 0
maxkey-identitys/maxkey-identity-kafka/src/main/java/org/maxkey/identity/kafka/KafkaIdentityAction.java

@@ -0,0 +1,10 @@
+package org.maxkey.identity.kafka;
+
+public class KafkaIdentityAction {
+    
+    public static String  CREATE_ACTION = "CREATE_ACTION";
+    public static String  DELETE_ACTION = "DELETE_ACTION";
+    public static String  UPDATE_ACTION = "UPDATE_ACTION";
+    public static String  PASSWORD_ACTION = "PASSWORD_ACTION";
+    
+}

+ 11 - 0
maxkey-identitys/maxkey-identity-kafka/src/main/java/org/maxkey/identity/kafka/KafkaIdentityTopic.java

@@ -0,0 +1,11 @@
+package org.maxkey.identity.kafka;
+
+public class KafkaIdentityTopic {
+    
+    public final static String  USERINFO_TOPIC = "IDENTITY_USERINFO_TOPIC";
+    public final  static String  ORG_TOPIC = "IDENTITY_ORG_TOPIC";
+    public final  static String  GROUP_TOPIC = "IDENTITY_GROUP_TOPIC";
+    public final  static String  PASSWORD_TOPIC = "IDENTITY_PASSWORD_TOPIC";
+    
+    
+}

+ 42 - 0
maxkey-identitys/maxkey-identity-kafka/src/main/java/org/maxkey/identity/kafka/KafkaMessage.java

@@ -0,0 +1,42 @@
+package org.maxkey.identity.kafka;
+
+public class KafkaMessage {
+    String topic;
+    String actionType;
+    String sendTime;
+    String msgId;
+    String content;
+    
+    public String getTopic() {
+        return topic;
+    }
+    public void setTopic(String topic) {
+        this.topic = topic;
+    }
+    public String getActionType() {
+        return actionType;
+    }
+    public void setActionType(String actionType) {
+        this.actionType = actionType;
+    }
+    public String getSendTime() {
+        return sendTime;
+    }
+    public void setSendTime(String sendTime) {
+        this.sendTime = sendTime;
+    }
+    public String getMsgId() {
+        return msgId;
+    }
+    public void setMsgId(String msgId) {
+        this.msgId = msgId;
+    }
+    public Object getContent() {
+        return content;
+    }
+    public void setContent(String content) {
+        this.content = content;
+    }
+    public KafkaMessage() {
+    }
+}

+ 48 - 0
maxkey-identitys/maxkey-identity-kafka/src/main/java/org/maxkey/identity/kafka/KafkaProvisioningService.java

@@ -0,0 +1,48 @@
+package org.maxkey.identity.kafka;
+
+import java.util.UUID;
+
+import org.maxkey.config.ApplicationConfig;
+import org.maxkey.util.DateUtils;
+import org.maxkey.util.JsonUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.kafka.core.KafkaTemplate;
+import org.springframework.stereotype.Component;
+
+@Component
+public class KafkaProvisioningService {
+    
+    private static final Logger _logger = LoggerFactory.getLogger(KafkaProvisioningService.class);
+    
+    @Autowired
+    protected ApplicationConfig applicationConfig;
+    
+    @Autowired
+    protected KafkaTemplate<String, String> kafkaTemplate;
+
+    public void setApplicationConfig(ApplicationConfig applicationConfig) {
+        this.applicationConfig = applicationConfig;
+    }
+
+    public void setKafkaTemplate(KafkaTemplate<String, String> kafkaTemplate) {
+        this.kafkaTemplate = kafkaTemplate;
+    }
+    
+    public void send(String topic,Object content,String actionType) {
+        if(applicationConfig.isKafkaSupport()) {
+            KafkaMessage message = new KafkaMessage();
+            message.setMsgId(UUID.randomUUID().toString());
+            message.setActionType(actionType);
+            message.setTopic(topic);
+            message.setSendTime(DateUtils.getCurrentDateTimeAsString());
+            message.setContent(JsonUtils.gson2Json(content));
+            String msg = JsonUtils.gson2Json(message);
+            _logger.info("send  message = {}", msg);
+            
+            kafkaTemplate.send(topic, msg);
+        }
+    }
+    
+}

+ 14 - 0
maxkey-identitys/maxkey-identity-scim/.settings/org.eclipse.jdt.core.prefs

@@ -0,0 +1,14 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=warning
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.mainOnlyProjectHasTestOnlyDependency=error
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.classpath.outputOverlappingAnotherSource=error
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error

+ 3 - 0
maxkey-identitys/maxkey-identity-scim/.settings/org.eclipse.jdt.launching.prefs

@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.launching.PREF_COMPILER_COMPLIANCE_DOES_NOT_MATCH_JRE=warning
+org.eclipse.jdt.launching.PREF_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE=warning

+ 13 - 0
maxkey-protocols/maxkey-protocol-saml-2.0/.settings/org.eclipse.jdt.core.prefs

@@ -1,4 +1,17 @@
 eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=warning
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.mainOnlyProjectHasTestOnlyDependency=error
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.classpath.outputOverlappingAnotherSource=error
 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
 org.eclipse.jdt.core.compiler.source=1.8
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error

+ 3 - 0
maxkey-protocols/maxkey-protocol-saml-2.0/.settings/org.eclipse.jdt.launching.prefs

@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.launching.PREF_COMPILER_COMPLIANCE_DOES_NOT_MATCH_JRE=warning
+org.eclipse.jdt.launching.PREF_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE=warning

+ 1 - 0
maxkey-web-manage/.project

@@ -10,6 +10,7 @@
 		<project>maxkey-client-sdk</project>
 		<project>maxkey-protocol-oauth-2.0</project>
 		<project>maxkey-protocol-saml-2.0</project>
+		<project>maxkey-identity-scim</project>
 	</projects>
 	<buildSpec>
 		<buildCommand>

+ 2 - 1
maxkey-web-manage/build.gradle

@@ -22,7 +22,8 @@ dependencies {
    	compile project(":maxkey-client-sdk")
    	compile project(":maxkey-protocols:maxkey-protocol-oauth-2.0")
    	compile project(":maxkey-protocols:maxkey-protocol-saml-2.0")   
-   	compile project(":maxkey-identitys:maxkey-identity-scim")   	
+   	compile project(":maxkey-identitys:maxkey-identity-scim")   
+   	compile project(":maxkey-identitys:maxkey-identity-kafka")	
    	
 }
 

+ 1 - 0
maxkey-web-manage/src/main/java/org/maxkey/MaxKeyMgtApplication.java

@@ -34,6 +34,7 @@ import org.springframework.context.annotation.ImportResource;
     "org.maxkey.dao",
     "org.maxkey.web",
     "org.maxkey.web.tag",
+    "org.maxkey.identity.kafka",
     "org.maxkey.identity.scim.controller"
 })
 @MapperScan("org.maxkey.dao.persistence,")

+ 23 - 1
maxkey-web-manage/src/main/resources/application.properties

@@ -59,4 +59,26 @@ spring.messages.basename=classpath:messages/message
 spring.messages.encoding=UTF-8
 #main
 spring.main.banner-mode=log
-spring.main.allow-bean-definition-overriding=true
+spring.main.allow-bean-definition-overriding=true
+
+###########【Kafka集群】###########
+spring.kafka.bootstrap-servers=localhost:9092
+###########【初始化生产者配置】###########
+# 重试次数
+spring.kafka.producer.retries=0
+# 应答级别:多少个分区副本备份完成时向生产者发送ack确认(可选0、1、all/-1)
+spring.kafka.producer.acks=1
+# 批量大小
+spring.kafka.producer.batch-size=16384
+# 提交延时
+spring.kafka.producer.properties.linger.ms=0
+# 当生产端积累的消息达到batch-size或接收到消息linger.ms后,生产者就会将消息提交给kafka
+# linger.ms为0表示每接收到一条消息就提交给kafka,这时候batch-size其实就没用了
+
+# 生产端缓冲区大小
+spring.kafka.producer.buffer-memory = 33554432
+# Kafka提供的序列化和反序列化类
+spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer
+spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer
+# 自定义分区器
+# spring.kafka.producer.properties.partitioner.class=com.felix.kafka.producer.CustomizePartitioner

+ 2 - 0
maxkey-web-manage/src/main/resources/maxkey.properties

@@ -11,6 +11,8 @@ config.server.default.uri=${config.server.prefix.uri}/main
 config.maxkey.uri=${config.server.name}/maxkey
 #InMemory 0 , jdbc  1, Redis 2 
 config.server.persistence=0
+#identity
+config.identity.kafkasupport=true
 ############################################################################
 #                Login configuration
 #enable captcha

+ 22 - 0
maxkey-web-maxkey/src/main/resources/application.properties

@@ -68,3 +68,25 @@ spring.messages.encoding=UTF-8
 #main
 spring.main.banner-mode=log
 spring.main.allow-bean-definition-overriding=true
+
+###########【Kafka集群】###########
+spring.kafka.bootstrap-servers=localhost:9092
+###########【初始化生产者配置】###########
+# 重试次数
+spring.kafka.producer.retries=0
+# 应答级别:多少个分区副本备份完成时向生产者发送ack确认(可选0、1、all/-1)
+spring.kafka.producer.acks=1
+# 批量大小
+spring.kafka.producer.batch-size=16384
+# 提交延时
+spring.kafka.producer.properties.linger.ms=0
+# 当生产端积累的消息达到batch-size或接收到消息linger.ms后,生产者就会将消息提交给kafka
+# linger.ms为0表示每接收到一条消息就提交给kafka,这时候batch-size其实就没用了
+
+# 生产端缓冲区大小
+spring.kafka.producer.buffer-memory = 33554432
+# Kafka提供的序列化和反序列化类
+spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer
+spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer
+# 自定义分区器
+# spring.kafka.producer.properties.partitioner.class=com.felix.kafka.producer.CustomizePartitioner

+ 3 - 0
maxkey-web-maxkey/src/main/resources/maxkey.properties

@@ -11,6 +11,9 @@ config.server.default.uri=${config.server.prefix.uri}/maxkey/appList
 config.server.management.uri=${config.server.name}:9521/maxkey-mgt/login
 #InMemory 0 , jdbc  1, Redis 2 
 config.server.persistence=0
+#identity
+config.identity.kafkasupport=false
+
 config.app.issuer=CN=ConSec,CN=COM,CN=SH
 ############################################################################
 #                Login configuration

+ 7 - 0
settings.gradle

@@ -11,6 +11,13 @@ include 'maxkey-authentications'
 
 //identity
 include 'maxkey-identitys:maxkey-identity-scim'
+include 'maxkey-identitys:maxkey-identity-kafka'
+
+
+//connectors
+include 'maxkey-connectors:maxkey-connector-base'
+include 'maxkey-connectors:maxkey-connector-ldap'
+include 'maxkey-connectors:maxkey-connector-activedirectory'
 
 //Protocol
 //include 'maxkey-protocols'