connectors

This commit is contained in:
shimingxy 2020-07-08 08:26:18 +08:00
parent a952c5addb
commit 7f17ce92ef
92 changed files with 3372 additions and 2325 deletions

View File

@ -292,6 +292,7 @@ subprojects {
compile group: 'org.apache.santuario', name: 'xmlsec', version: '1.5.8' compile group: 'org.apache.santuario', name: 'xmlsec', version: '1.5.8'
compile group: 'org.ogce', name: 'xpp3', version: '1.1.6' compile group: 'org.ogce', name: 'xpp3', version: '1.1.6'
compile group: 'com.thoughtworks.xstream', name: 'xstream', version: '1.4.10' compile group: 'com.thoughtworks.xstream', name: 'xstream', version: '1.4.10'
//local jars //local jars
compile fileTree(dir: "${rootDir}/maxkey-lib/", include: '*.jar') compile fileTree(dir: "${rootDir}/maxkey-lib/", include: '*.jar')
// //

View File

@ -13,6 +13,12 @@
<attribute name="test" value="true"/> <attribute name="test" value="true"/>
</attributes> </attributes>
</classpathentry> </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="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.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="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="output" path="bin/default"/> <classpathentry kind="output" path="bin/default"/>

View File

@ -2,5 +2,6 @@
<wb-module deploy-name="maxkey-client-sdk"> <wb-module deploy-name="maxkey-client-sdk">
<wb-resource deploy-path="/" source-path="/src/main/java"/> <wb-resource deploy-path="/" source-path="/src/main/java"/>
<wb-resource deploy-path="/" source-path="/src/test/java"/> <wb-resource deploy-path="/" source-path="/src/test/java"/>
<wb-resource deploy-path="/" source-path="/src/main/resources"/>
</wb-module> </wb-module>
</project-modules> </project-modules>

View File

@ -1,10 +1,12 @@
description = "maxkey-client-sdk" description = "maxkey-client-sdk"
dependencies { dependencies {
compile fileTree(dir: '../maxkey-lib/log/', include: '*slf4j*.jar') /*compile group: 'commons-io', name: 'commons-io', version: '2.6'
compile fileTree(dir: '../maxkey-lib/log/', include: 'log4j*.jar') compile group: 'commons-logging', name: 'commons-logging', version: '1.2'
compile fileTree(dir: '../maxkey-lib/apache/', include: 'commons-logging*.jar') compile group: 'log4j', name: 'log4j', version: '1.2.17'
compile fileTree(dir: '../maxkey-lib/apache/', include: 'commons-codec*.jar') compile group: 'org.slf4j', name: 'slf4j-api', version: '1.5.11'
compile fileTree(dir: '../maxkey-lib/json/', include: 'gson*.jar') compile group: 'commons-codec', name: 'commons-codec', version: '1.14'
compile fileTree(dir: '../maxkey-lib/java/', include: '*.jar') compile group: 'com.nimbusds', name: 'nimbus-jose-jwt', version: '8.10'
compile group: 'com.google.code.gson', name: 'gson', version: '2.8.6'
*/
} }

Binary file not shown.

View File

@ -0,0 +1,106 @@
package org.maxkey.client.http;
/*
public class ApacheHttpClient{
private final CloseableHttpAsyncClient client;
public ApacheHttpClient() {
this(ApacheHttpClientConfig.defaultConfig());
}
public ApacheHttpClient(ApacheHttpClientConfig config) {
this(config.getHttpAsyncClientBuilder());
}
public ApacheHttpClient(HttpAsyncClientBuilder builder) {
this(builder.build());
}
public ApacheHttpClient(CloseableHttpAsyncClient client) {
this.client = client;
this.client.start();
}
@Override
public void close() throws IOException {
client.close();
}
@Override
public <T> Future<T> executeAsync(String userAgent, Map<String, String> headers, Verb httpVerb, String completeUrl,
byte[] bodyContents, OAuthAsyncRequestCallback<T> callback, OAuthRequest.ResponseConverter<T> converter) {
final HttpEntity entity = bodyContents == null ? null : new ByteArrayEntity(bodyContents);
return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, entity, callback, converter);
}
@Override
public <T> Future<T> executeAsync(String userAgent, Map<String, String> headers, Verb httpVerb, String completeUrl,
MultipartPayload bodyContents, OAuthAsyncRequestCallback<T> callback,
OAuthRequest.ResponseConverter<T> converter) {
throw new UnsupportedOperationException("ApacheHttpClient does not support MultipartPayload yet.");
}
@Override
public <T> Future<T> executeAsync(String userAgent, Map<String, String> headers, Verb httpVerb, String completeUrl,
String bodyContents, OAuthAsyncRequestCallback<T> callback, OAuthRequest.ResponseConverter<T> converter) {
final HttpEntity entity = bodyContents == null ? null : new StringEntity(bodyContents, StandardCharsets.UTF_8);
return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, entity, callback, converter);
}
@Override
public <T> Future<T> executeAsync(String userAgent, Map<String, String> headers, Verb httpVerb, String completeUrl,
File bodyContents, OAuthAsyncRequestCallback<T> callback, OAuthRequest.ResponseConverter<T> converter) {
final HttpEntity entity = bodyContents == null ? null : new FileEntity(bodyContents);
return doExecuteAsync(userAgent, headers, httpVerb, completeUrl, entity, callback, converter);
}
private <T> Future<T> doExecuteAsync(String userAgent, Map<String, String> headers, Verb httpVerb,
String completeUrl, HttpEntity entity, OAuthAsyncRequestCallback<T> callback,
OAuthRequest.ResponseConverter<T> converter) {
final RequestBuilder builder = getRequestBuilder(httpVerb);
builder.setUri(completeUrl);
if (httpVerb.isPermitBody()) {
if (!headers.containsKey(CONTENT_TYPE)) {
builder.addHeader(CONTENT_TYPE, DEFAULT_CONTENT_TYPE);
}
builder.setEntity(entity);
}
for (Map.Entry<String, String> header : headers.entrySet()) {
builder.addHeader(header.getKey(), header.getValue());
}
if (userAgent != null) {
builder.setHeader(OAuthConstants.USER_AGENT_HEADER_NAME, userAgent);
}
final OAuthAsyncCompletionHandler<T> handler = new OAuthAsyncCompletionHandler<>(callback, converter);
final Future<HttpResponse> future = client.execute(builder.build(), handler);
return new ApacheHttpFuture<>(future, handler);
}
private static RequestBuilder getRequestBuilder(Verb httpVerb) {
switch (httpVerb) {
case GET:
return RequestBuilder.get();
case PUT:
return RequestBuilder.put();
case DELETE:
return RequestBuilder.delete();
case HEAD:
return RequestBuilder.head();
case POST:
return RequestBuilder.post();
case PATCH:
return RequestBuilder.patch();
case TRACE:
return RequestBuilder.trace();
case OPTIONS:
return RequestBuilder.options();
default:
throw new IllegalArgumentException("message build error: unknown verb type");
}
}
}*/

View File

@ -1,160 +0,0 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.client.oauth.builder.api;
import org.maxkey.client.http.HttpVerb;
import org.maxkey.client.oauth.extractors.*;
import org.maxkey.client.oauth.model.*;
import org.maxkey.client.oauth.oauth.*;
import org.maxkey.client.oauth.services.*;
/**
* Default implementation of the OAuth protocol, version 1.0a
*
* This class is meant to be extended by concrete implementations of the API,
* providing the endpoints and endpoint-http-verbs.
*
* If your Api adheres to the 1.0a protocol correctly, you just need to extend
* this class and define the getters for your endpoints.
*
* If your Api does something a bit different, you can override the different
* extractors or services, in order to fine-tune the process. Please read the
* javadocs of the interfaces to get an idea of what to do.
*
* @author Pablo Fernandez
*
*/
public abstract class DefaultApi10a implements Api
{
/**
* Returns the access token extractor.
*
* @return access token extractor
*/
public AccessTokenExtractor getAccessTokenExtractor()
{
return new TokenExtractorImpl();
}
/**
* Returns the base string extractor.
*
* @return base string extractor
*/
public BaseStringExtractor getBaseStringExtractor()
{
return new BaseStringExtractorImpl();
}
/**
* Returns the header extractor.
*
* @return header extractor
*/
public HeaderExtractor getHeaderExtractor()
{
return new HeaderExtractorImpl();
}
/**
* Returns the request token extractor.
*
* @return request token extractor
*/
public RequestTokenExtractor getRequestTokenExtractor()
{
return new TokenExtractorImpl();
}
/**
* Returns the signature service.
*
* @return signature service
*/
public SignatureService getSignatureService()
{
return new HMACSha1SignatureService();
}
/**
* Returns the timestamp service.
*
* @return timestamp service
*/
public TimestampService getTimestampService()
{
return new TimestampServiceImpl();
}
/**
* Returns the verb for the access token endpoint (defaults to POST)
*
* @return access token endpoint verb
*/
public HttpVerb getAccessTokenVerb()
{
return HttpVerb.POST;
}
/**
* Returns the verb for the request token endpoint (defaults to POST)
*
* @return request token endpoint verb
*/
public HttpVerb getRequestTokenVerb()
{
return HttpVerb.POST;
}
/**
* Returns the URL that receives the request token requests.
*
* @return request token URL
*/
public abstract String getRequestTokenEndpoint();
/**
* Returns the URL that receives the access token requests.
*
* @return access token URL
*/
public abstract String getAccessTokenEndpoint();
/**
* Returns the URL where you should redirect your users to authenticate
* your application.
*
* @param requestToken the request token you need to authorize
* @return the URL where you should redirect your users
*/
public abstract String getAuthorizationUrl(Token requestToken);
/**
* Returns the {@link OAuthService} for this Api
*
* @param apiKey Key
* @param apiSecret Api Secret
* @param callback OAuth callback (either URL or 'oob')
* @param scope OAuth scope (optional)
*/
public OAuthService createService(OAuthConfig config)
{
return new OAuth10aServiceImpl(this, config);
}
}

View File

@ -1,49 +0,0 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.client.oauth.builder.api;
import org.maxkey.client.oauth.model.Token;
public class MaxkeyApi10a extends DefaultApi10a
{
private static final String DEFAULT_WEB_URL = "https://sso.maxkey.top/maxkey";
private static final String AUTHORIZATION_URL = DEFAULT_WEB_URL+"/oauth/v10a/authz?oauth_token=%s";
public MaxkeyApi10a() {
}
@Override
public String getAccessTokenEndpoint()
{
return DEFAULT_WEB_URL+"/oauth/v10a/access_token";
}
@Override
public String getRequestTokenEndpoint()
{
return DEFAULT_WEB_URL+"/oauth/v10a/request_token";
}
@Override
public String getAuthorizationUrl(Token requestToken)
{
return String.format(AUTHORIZATION_URL, requestToken.getToken());
}
}

View File

@ -1,86 +0,0 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.client.oauth.builder.api;
import org.maxkey.client.oauth.model.*;
public class OAuthApi10a extends DefaultApi10a
{
//private static final String REQUEST_TOKEN_URL = "http://api.t.sina.com.cn/oauth/request_token";
//private static final String ACCESS_TOKEN_URL = "http://api.t.sina.com.cn/oauth/access_token";
//private static final String AUTHORIZE_URL = "http://api.t.sina.com.cn/oauth/authorize?oauth_token=%s";
private String requestTokenUrl;
private String accessTokenUrl;
private String authorizeUrl;
public OAuthApi10a(String requestTokenUrl,String authorizeUrl, String accessTokenUrl) {
super();
this.requestTokenUrl = requestTokenUrl;
this.authorizeUrl = authorizeUrl;
this.accessTokenUrl = accessTokenUrl;
}
@Override
public String getRequestTokenEndpoint()
{
return requestTokenUrl;
}
@Override
public String getAccessTokenEndpoint()
{
return accessTokenUrl;
}
@Override
public String getAuthorizationUrl(Token requestToken)
{
return String.format(authorizeUrl, requestToken.getToken());
}
public String getRequestTokenUrl() {
return requestTokenUrl;
}
public void setRequestTokenUrl(String requestTokenUrl) {
this.requestTokenUrl = requestTokenUrl;
}
public String getAccessTokenUrl() {
return accessTokenUrl;
}
public void setAccessTokenUrl(String accessTokenUrl) {
this.accessTokenUrl = accessTokenUrl;
}
public String getAuthorizeUrl() {
return authorizeUrl;
}
public void setAuthorizeUrl(String authorizeUrl) {
this.authorizeUrl = authorizeUrl;
}
@Override
public String toString() {
return "OAuthApi10a [requestTokenUrl=" + requestTokenUrl
+ ", accessTokenUrl=" + accessTokenUrl + ", authorizeUrl="
+ authorizeUrl + "]";
}
}

View File

@ -1,240 +0,0 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.client.oauth.oauth;
import java.util.*;
import java.util.concurrent.TimeUnit;
import org.maxkey.client.http.Request;
import org.maxkey.client.http.RequestTuner;
import org.maxkey.client.http.Response;
import org.maxkey.client.oauth.builder.api.*;
import org.maxkey.client.oauth.model.*;
import org.maxkey.client.oauth.services.*;
import org.maxkey.client.utils.MapUtils;
/**
* OAuth 1.0a implementation of {@link OAuthService}
*
* @author Pablo Fernandez
*/
public class OAuth10aServiceImpl implements OAuthService
{
private static final String VERSION = "1.0";
private OAuthConfig config;
private DefaultApi10a api;
/**
* Default constructor
*
* @param api OAuth1.0a api information
* @param config OAuth 1.0a configuration param object
*/
public OAuth10aServiceImpl(DefaultApi10a api, OAuthConfig config)
{
this.api = api;
this.config = config;
}
/**
* Default constructor
*
* @param clientId
* @param clientSecret
* @param redirectUri
*/
public OAuth10aServiceImpl(String clientId, String clientSecret,String redirectUri)
{
this.api = new MaxkeyApi10a();
this.config =new OAuthConfig(clientId,clientSecret,redirectUri);
}
/**
* {@inheritDoc}
*/
public Token getRequestToken(int timeout, TimeUnit unit)
{
return getRequestToken(new TimeoutTuner(timeout, unit));
}
public Token getRequestToken()
{
return getRequestToken(2, TimeUnit.SECONDS);
}
public Token getRequestToken(RequestTuner tuner)
{
config.log("obtaining request token from " + api.getRequestTokenEndpoint());
OAuthRequest request = new OAuthRequest(api.getRequestTokenVerb(), api.getRequestTokenEndpoint());
config.log("setting oauth_callback to " + config.getCallback());
request.addOAuthParameter(OAuthConstants.CALLBACK, config.getCallback());
addOAuthParams(request, OAuthConstants.EMPTY_TOKEN);
appendSignature(request);
config.log("sending request...");
Response response = request.send(tuner);
String body = response.getBody();
config.log("response status code: " + response.getCode());
config.log("response body: " + body);
return api.getRequestTokenExtractor().extract(body);
}
private void addOAuthParams(OAuthRequest request, Token token)
{
request.addOAuthParameter(OAuthConstants.TIMESTAMP, api.getTimestampService().getTimestampInSeconds());
request.addOAuthParameter(OAuthConstants.NONCE, api.getTimestampService().getNonce());
request.addOAuthParameter(OAuthConstants.CONSUMER_KEY, config.getApiKey());
request.addOAuthParameter(OAuthConstants.SIGN_METHOD, api.getSignatureService().getSignatureMethod());
request.addOAuthParameter(OAuthConstants.VERSION, getVersion());
if(config.hasScope()) request.addOAuthParameter(OAuthConstants.SCOPE, config.getScope());
request.addOAuthParameter(OAuthConstants.SIGNATURE, getSignature(request, token));
config.log("appended additional OAuth parameters: " + MapUtils.toString(request.getOauthParameters()));
}
/**
* {@inheritDoc}
*/
public Token getAccessToken(Token requestToken, Verifier verifier, int timeout, TimeUnit unit)
{
return getAccessToken(requestToken, verifier, new TimeoutTuner(timeout, unit));
}
public Token getAccessToken(Token requestToken, Verifier verifier)
{
return getAccessToken(requestToken, verifier, 2, TimeUnit.SECONDS);
}
public Token getAccessToken(Token requestToken, Verifier verifier, RequestTuner tuner)
{
config.log("obtaining access token from " + api.getAccessTokenEndpoint());
OAuthRequest request = new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint());
request.addOAuthParameter(OAuthConstants.TOKEN, requestToken.getToken());
request.addOAuthParameter(OAuthConstants.VERIFIER, verifier.getValue());
config.log("setting token to: " + requestToken + " and verifier to: " + verifier);
addOAuthParams(request, requestToken);
appendSignature(request);
Response response = request.send(tuner);
return api.getAccessTokenExtractor().extract(response.getBody());
}
/**
* {@inheritDoc}
*/
public void signRequest(Token token, OAuthRequest request)
{
config.log("signing request: " + request.getCompleteUrl());
// Do not append the token if empty. This is for two legged OAuth calls.
if (!token.isEmpty())
{
request.addOAuthParameter(OAuthConstants.TOKEN, token.getToken());
}
config.log("setting token to: " + token);
addOAuthParams(request, token);
appendSignature(request);
}
/**
* {@inheritDoc}
*/
public String getVersion()
{
return VERSION;
}
/**
* {@inheritDoc}
*/
public String getAuthorizationUrl(Token requestToken)
{
return api.getAuthorizationUrl(requestToken);
}
private String getSignature(OAuthRequest request, Token token)
{
config.log("generating signature...");
config.log("using base64 encoder: " + Base64Encoder.type());
String baseString = api.getBaseStringExtractor().extract(request);
String signature = api.getSignatureService().getSignature(baseString, config.getApiSecret(), token.getSecret());
config.log("base string is: " + baseString);
config.log("signature is: " + signature);
return signature;
}
private void appendSignature(OAuthRequest request)
{
switch (config.getSignatureType())
{
case Header:
config.log("using Http Header signature");
String oauthHeader = api.getHeaderExtractor().extract(request);
request.addHeader(OAuthConstants.HEADER, oauthHeader);
break;
case QueryString:
config.log("using Querystring signature");
for (Map.Entry<String, String> entry : request.getOauthParameters().entrySet())
{
request.addQuerystringParameter(entry.getKey(), entry.getValue());
}
break;
}
}
private static class TimeoutTuner extends RequestTuner
{
private final int duration;
private final TimeUnit unit;
public TimeoutTuner(int duration, TimeUnit unit)
{
this.duration = duration;
this.unit = unit;
}
@Override
public void tune(Request request)
{
request.setReadTimeout(duration, unit);
}
}
@Override
public void signAccessTokenRequest(Token accessToken, OAuthRequest request) {
// TODO Auto-generated method stub
config.log("signing request: " + request.getCompleteUrl());
// Do not append the token if empty. This is for two legged OAuth calls.
if (!accessToken.isEmpty())
{
request.addQuerystringParameter(OAuthConstants.ACCESS_TOKEN, accessToken.getToken());
}else{
throw new IllegalArgumentException("accessToken can not be null .");
}
config.log("setting token to: " + accessToken);
}
}

View File

@ -50,7 +50,7 @@ public class AuthenticationFilter implements Filter {
private static final String UUID_REGEX = "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$"; private static final String UUID_REGEX = "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$";
public static final String CONST_CONNSEC_USERINFO="CONST_CONNSEC_USERINFO"; public static final String CONST_MAXKEY_USERINFO="CONST_MAXKEY_USERINFO";
private String clientId; private String clientId;
private String clientSecret; private String clientSecret;
@ -77,9 +77,9 @@ public class AuthenticationFilter implements Filter {
UserInfo userInfo=restClient.getUserInfo(accessToken.getToken()); UserInfo userInfo=restClient.getUserInfo(accessToken.getToken());
session.setAttribute(CONST_CONNSEC_USERINFO, userInfo); session.setAttribute(CONST_MAXKEY_USERINFO, userInfo);
}else if(session.getAttribute(CONST_CONNSEC_USERINFO)==null){ }else if(session.getAttribute(CONST_MAXKEY_USERINFO)==null){
String authorizationUrl = service.getAuthorizationUrl(EMPTY_TOKEN); String authorizationUrl = service.getAuthorizationUrl(EMPTY_TOKEN);
log.debug("Redirect to authorization Url : "+authorizationUrl); log.debug("Redirect to authorization Url : "+authorizationUrl);
httpServletResponse.sendRedirect(authorizationUrl); httpServletResponse.sendRedirect(authorizationUrl);

View File

@ -46,7 +46,7 @@ public class SingleSignOutFilter implements Filter {
HttpServletResponse httpServletResponse = (HttpServletResponse) response; HttpServletResponse httpServletResponse = (HttpServletResponse) response;
HttpSession session = httpServletRequest.getSession(); HttpSession session = httpServletRequest.getSession();
session.removeAttribute(AuthenticationFilter.CONST_CONNSEC_USERINFO); session.removeAttribute(AuthenticationFilter.CONST_MAXKEY_USERINFO);
session.invalidate(); session.invalidate();
httpServletResponse.sendRedirect(singleSignOutEndpoint); httpServletResponse.sendRedirect(singleSignOutEndpoint);

View File

@ -15,7 +15,7 @@
*/ */
package com.connsec.client.oauth.test; package org.maxkey.client.oauth.test;
import java.util.*; import java.util.*;

View File

@ -15,7 +15,7 @@
*/ */
package com.connsec.client.oauth.test; package org.maxkey.client.oauth.test;
import org.maxkey.client.http.Response; import org.maxkey.client.http.Response;
import org.maxkey.client.oauth.builder.api.MaxkeyPasswordApi20; import org.maxkey.client.oauth.builder.api.MaxkeyPasswordApi20;

View File

@ -22,4 +22,4 @@
* @author Administrator * @author Administrator
* *
*/ */
package com.connsec.client.oauth.test; package org.maxkey.client.oauth.test;

View File

@ -15,7 +15,7 @@
*/ */
package com.connsec.client.utils; package org.maxkey.client.utils;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLDecoder; import java.net.URLDecoder;

View File

@ -22,4 +22,4 @@
* @author Administrator * @author Administrator
* *
*/ */
package com.connsec.client.utils; package org.maxkey.client.utils;

View File

@ -15,7 +15,7 @@
*/ */
package com.connsec.rest; package org.maxkey.rest;
import java.util.HashMap; import java.util.HashMap;

View File

@ -21,12 +21,17 @@ import java.util.Optional;
import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.maxkey.connector.GroupConnector; import org.maxkey.connector.GroupConnector;
import org.maxkey.domain.Groups;
import org.maxkey.identity.kafka.KafkaIdentityAction;
import org.maxkey.identity.kafka.KafkaIdentityTopic; import org.maxkey.identity.kafka.KafkaIdentityTopic;
import org.maxkey.identity.kafka.KafkaMessage;
import org.maxkey.util.JsonUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener; import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@Component @Component
public class KafkaGroupsTopicReceiver { public class KafkaGroupsTopicReceiver {
private static final Logger _logger = LoggerFactory.getLogger(KafkaGroupsTopicReceiver.class); private static final Logger _logger = LoggerFactory.getLogger(KafkaGroupsTopicReceiver.class);
@ -36,15 +41,31 @@ public class KafkaGroupsTopicReceiver {
@KafkaListener(topics = {KafkaIdentityTopic.GROUP_TOPIC}) @KafkaListener(topics = {KafkaIdentityTopic.GROUP_TOPIC})
public void listen(ConsumerRecord<?, ?> record) { public void listen(ConsumerRecord<?, ?> record) {
try {
Optional<?> kafkaMessage = Optional.ofNullable(record.value()); Optional<?> kafkaMessage = Optional.ofNullable(record.value());
if (kafkaMessage.isPresent()) { if (kafkaMessage.isPresent()) {
Object message = kafkaMessage.get(); Object message = kafkaMessage.get();
_logger.info("----------------- record =" + record); _logger.debug("----------------- record =" + record);
_logger.info("------------------ message =" + message); _logger.debug("------------------ message =" + message);
KafkaMessage receiverMessage = JsonUtils.gson2Object(message.toString(), KafkaMessage.class);
Groups group = JsonUtils.gson2Object(receiverMessage.getContent().toString(),Groups.class);
if(receiverMessage.getActionType().equalsIgnoreCase(KafkaIdentityAction.CREATE_ACTION)) {
groupConnector.create(group);
}else if(receiverMessage.getActionType().equalsIgnoreCase(KafkaIdentityAction.UPDATE_ACTION)) {
groupConnector.update(group);
}else if(receiverMessage.getActionType().equalsIgnoreCase(KafkaIdentityAction.DELETE_ACTION)) {
groupConnector.delete(group);
}else{
_logger.info("Other Action ");
}
}
}catch(Exception e) {
} }
} }

View File

@ -21,12 +21,17 @@ import java.util.Optional;
import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.maxkey.connector.OrganizationConnector; import org.maxkey.connector.OrganizationConnector;
import org.maxkey.domain.Organizations;
import org.maxkey.identity.kafka.KafkaIdentityAction;
import org.maxkey.identity.kafka.KafkaIdentityTopic; import org.maxkey.identity.kafka.KafkaIdentityTopic;
import org.maxkey.identity.kafka.KafkaMessage;
import org.maxkey.util.JsonUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener; import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@Component @Component
public class KafkaOrgsTopicReceiver { public class KafkaOrgsTopicReceiver {
private static final Logger _logger = LoggerFactory.getLogger(KafkaOrgsTopicReceiver.class); private static final Logger _logger = LoggerFactory.getLogger(KafkaOrgsTopicReceiver.class);
@ -36,15 +41,31 @@ public class KafkaOrgsTopicReceiver {
@KafkaListener(topics = {KafkaIdentityTopic.ORG_TOPIC}) @KafkaListener(topics = {KafkaIdentityTopic.ORG_TOPIC})
public void listen(ConsumerRecord<?, ?> record) { public void listen(ConsumerRecord<?, ?> record) {
try {
Optional<?> kafkaMessage = Optional.ofNullable(record.value()); Optional<?> kafkaMessage = Optional.ofNullable(record.value());
if (kafkaMessage.isPresent()) { if (kafkaMessage.isPresent()) {
Object message = kafkaMessage.get(); Object message = kafkaMessage.get();
_logger.info("----------------- record =" + record); _logger.debug("----------------- record =" + record);
_logger.info("------------------ message =" + message); _logger.debug("------------------ message =" + message);
KafkaMessage receiverMessage = JsonUtils.gson2Object(message.toString(), KafkaMessage.class);
Organizations org = JsonUtils.gson2Object(receiverMessage.getContent().toString(),Organizations.class);
if(receiverMessage.getActionType().equalsIgnoreCase(KafkaIdentityAction.CREATE_ACTION)) {
organizationConnector.create(org);
}else if(receiverMessage.getActionType().equalsIgnoreCase(KafkaIdentityAction.UPDATE_ACTION)) {
organizationConnector.update(org);
}else if(receiverMessage.getActionType().equalsIgnoreCase(KafkaIdentityAction.DELETE_ACTION)) {
organizationConnector.delete(org);
}else{
_logger.info("Other Action ");
}
}
}catch(Exception e) {
} }
} }

View File

@ -21,12 +21,17 @@ import java.util.Optional;
import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.maxkey.connector.PasswordConnector; import org.maxkey.connector.PasswordConnector;
import org.maxkey.domain.UserInfo;
import org.maxkey.identity.kafka.KafkaIdentityAction;
import org.maxkey.identity.kafka.KafkaIdentityTopic; import org.maxkey.identity.kafka.KafkaIdentityTopic;
import org.maxkey.identity.kafka.KafkaMessage;
import org.maxkey.util.JsonUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener; import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@Component @Component
public class KafkaPasswordTopicReceiver { public class KafkaPasswordTopicReceiver {
private static final Logger _logger = LoggerFactory.getLogger(KafkaPasswordTopicReceiver.class); private static final Logger _logger = LoggerFactory.getLogger(KafkaPasswordTopicReceiver.class);
@ -36,16 +41,27 @@ public class KafkaPasswordTopicReceiver {
@KafkaListener(topics = {KafkaIdentityTopic.PASSWORD_TOPIC}) @KafkaListener(topics = {KafkaIdentityTopic.PASSWORD_TOPIC})
public void listen(ConsumerRecord<?, ?> record) { public void listen(ConsumerRecord<?, ?> record) {
try {
Optional<?> kafkaMessage = Optional.ofNullable(record.value()); Optional<?> kafkaMessage = Optional.ofNullable(record.value());
if (kafkaMessage.isPresent()) { if (kafkaMessage.isPresent()) {
Object message = kafkaMessage.get(); Object message = kafkaMessage.get();
_logger.info("----------------- record =" + record); _logger.debug("----------------- record =" + record);
_logger.info("------------------ message =" + message); _logger.debug("------------------ message =" + message);
KafkaMessage receiverMessage = JsonUtils.gson2Object(message.toString(), KafkaMessage.class);
UserInfo userInfo = JsonUtils.gson2Object(receiverMessage.getContent().toString(),UserInfo.class);
if(receiverMessage.getActionType().equalsIgnoreCase(KafkaIdentityAction.PASSWORD_ACTION)) {
passwordConnector.update(userInfo);
}else{
_logger.info("Other Action ");
}
}
}catch(Exception e) {
} }
} }
} }

View File

@ -21,12 +21,17 @@ import java.util.Optional;
import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.maxkey.connector.UserInfoConnector; import org.maxkey.connector.UserInfoConnector;
import org.maxkey.domain.UserInfo;
import org.maxkey.identity.kafka.KafkaIdentityAction;
import org.maxkey.identity.kafka.KafkaIdentityTopic; import org.maxkey.identity.kafka.KafkaIdentityTopic;
import org.maxkey.identity.kafka.KafkaMessage;
import org.maxkey.util.JsonUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener; import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@Component @Component
public class KafkaUserInfoTopicReceiver { public class KafkaUserInfoTopicReceiver {
private static final Logger _logger = LoggerFactory.getLogger(KafkaUserInfoTopicReceiver.class); private static final Logger _logger = LoggerFactory.getLogger(KafkaUserInfoTopicReceiver.class);
@ -36,15 +41,31 @@ public class KafkaUserInfoTopicReceiver {
@KafkaListener(topics = {KafkaIdentityTopic.USERINFO_TOPIC}) @KafkaListener(topics = {KafkaIdentityTopic.USERINFO_TOPIC})
public void listen(ConsumerRecord<?, ?> record) { public void listen(ConsumerRecord<?, ?> record) {
try {
Optional<?> kafkaMessage = Optional.ofNullable(record.value()); Optional<?> kafkaMessage = Optional.ofNullable(record.value());
if (kafkaMessage.isPresent()) { if (kafkaMessage.isPresent()) {
Object message = kafkaMessage.get(); Object message = kafkaMessage.get();
_logger.info("----------------- record =" + record); _logger.debug("----------------- record =" + record);
_logger.info("------------------ message =" + message); _logger.debug("------------------ message =" + message);
KafkaMessage receiverMessage = JsonUtils.gson2Object(message.toString(), KafkaMessage.class);
UserInfo userInfo = JsonUtils.gson2Object(receiverMessage.getContent().toString(),UserInfo.class);
if(receiverMessage.getActionType().equalsIgnoreCase(KafkaIdentityAction.CREATE_ACTION)) {
userInfoConnector.create(userInfo);
}else if(receiverMessage.getActionType().equalsIgnoreCase(KafkaIdentityAction.UPDATE_ACTION)) {
userInfoConnector.update(userInfo);
}else if(receiverMessage.getActionType().equalsIgnoreCase(KafkaIdentityAction.DELETE_ACTION)) {
userInfoConnector.delete(userInfo);
}else{
_logger.info("Other Action ");
}
}
}catch(Exception e) {
} }
} }

View File

@ -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>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>maxkey-connector-dingding</name>
<comment>Project maxkey-connector-dingding 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>

View File

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

View File

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

View File

@ -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-dingding">
<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-persistence/maxkey-persistence">
<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>

View File

@ -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>

View File

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

View File

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

View File

@ -0,0 +1,72 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.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.dingding"
})
public class DingdingConsumerApplication {
public static void main(String[] args) {
// TODO Auto-generated method stub
ConfigurableApplicationContext context = SpringApplication.run(DingdingConsumerApplication.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(DingdingConsumerApplication.class);
}
}

View File

@ -0,0 +1,170 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.connector.dingding;
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 Group2Dingding extends GroupConnector {
private final static Logger logger = LoggerFactory.getLogger(Group2Dingding.class);
LdapUtils ldapUtils;
public Group2Dingding() {
}
@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;
}
}

View File

@ -0,0 +1,136 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.connector.dingding;
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 Organization2Dingding extends OrganizationConnector{
private final static Logger logger = LoggerFactory.getLogger(Organization2Dingding.class);
LdapUtils ldapUtils;
public Organization2Dingding() {
}
@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.getParentId()+"))", 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);
}
}

View File

@ -0,0 +1,62 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.connector.dingding;
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 Password2Dingding extends PasswordConnector{
private final static Logger logger = LoggerFactory.getLogger(Password2Dingding.class);
LdapUtils ldapUtils;
public Password2Dingding() {
}
@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;
}
}

View File

@ -0,0 +1,157 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.connector.dingding;
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 UserInfo2Dingding extends UserInfoConnector{
private final static Logger logger = LoggerFactory.getLogger(UserInfo2Dingding.class);
LdapUtils ldapUtils;
public UserInfo2Dingding() {
}
@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;
}
}

View File

@ -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=LdapConsumerGroup
# 是否自动提交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

View File

@ -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>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>maxkey-connector-feishu</name>
<comment>Project maxkey-connector-feishu 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>

View File

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

View File

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

View File

@ -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-feishu">
<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-persistence/maxkey-persistence">
<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>

View File

@ -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>

View File

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

View File

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

View File

@ -0,0 +1,72 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.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 FeishuConsumerApplication {
public static void main(String[] args) {
// TODO Auto-generated method stub
ConfigurableApplicationContext context = SpringApplication.run(FeishuConsumerApplication.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(FeishuConsumerApplication.class);
}
}

View File

@ -0,0 +1,170 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.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 Group2Feishu extends GroupConnector {
private final static Logger logger = LoggerFactory.getLogger(Group2Feishu.class);
LdapUtils ldapUtils;
public Group2Feishu() {
}
@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;
}
}

View File

@ -0,0 +1,136 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.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 Organization2Feishu extends OrganizationConnector{
private final static Logger logger = LoggerFactory.getLogger(Organization2Feishu.class);
LdapUtils ldapUtils;
public Organization2Feishu() {
}
@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.getParentId()+"))", 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);
}
}

View File

@ -0,0 +1,62 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.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 Password2Feishu extends PasswordConnector{
private final static Logger logger = LoggerFactory.getLogger(Password2Feishu.class);
LdapUtils ldapUtils;
public Password2Feishu() {
}
@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;
}
}

View File

@ -0,0 +1,157 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.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 UserInfo2Feishu extends UserInfoConnector{
private final static Logger logger = LoggerFactory.getLogger(UserInfo2Feishu.class);
LdapUtils ldapUtils;
public UserInfo2Feishu() {
}
@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;
}
}

View File

@ -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=LdapConsumerGroup
# 是否自动提交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

View File

@ -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>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>maxkey-connector-welink</name>
<comment>Project maxkey-connector-welink 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>

View File

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

View File

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

View File

@ -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-welink">
<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-persistence/maxkey-persistence">
<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>

View File

@ -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>

View File

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

View File

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

View File

@ -0,0 +1,72 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.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 WelinkConsumerApplication {
public static void main(String[] args) {
// TODO Auto-generated method stub
ConfigurableApplicationContext context = SpringApplication.run(WelinkConsumerApplication.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(WelinkConsumerApplication.class);
}
}

View File

@ -0,0 +1,170 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.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 Group2Welink extends GroupConnector {
private final static Logger logger = LoggerFactory.getLogger(Group2Welink.class);
LdapUtils ldapUtils;
public Group2Welink() {
}
@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;
}
}

View File

@ -0,0 +1,136 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.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 Organization2Welink extends OrganizationConnector{
private final static Logger logger = LoggerFactory.getLogger(Organization2Welink.class);
LdapUtils ldapUtils;
public Organization2Welink() {
}
@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.getParentId()+"))", 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);
}
}

View File

@ -0,0 +1,62 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.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 Password2Welink extends PasswordConnector{
private final static Logger logger = LoggerFactory.getLogger(Password2Welink.class);
LdapUtils ldapUtils;
public Password2Welink() {
}
@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;
}
}

View File

@ -0,0 +1,157 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.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 UserInfo2Welink extends UserInfoConnector{
private final static Logger logger = LoggerFactory.getLogger(UserInfo2Welink.class);
LdapUtils ldapUtils;
public UserInfo2Welink() {
}
@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;
}
}

View File

@ -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=LdapConsumerGroup
# 是否自动提交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

View File

@ -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>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>maxkey-connector-workweixin</name>
<comment>Project maxkey-connector-workweixin 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>

View File

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

View File

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

View File

@ -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-workweixin">
<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-persistence/maxkey-persistence">
<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>

View File

@ -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>

View File

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

View File

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

View File

@ -0,0 +1,72 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.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 WeixinConsumerApplication {
public static void main(String[] args) {
// TODO Auto-generated method stub
ConfigurableApplicationContext context = SpringApplication.run(WeixinConsumerApplication.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(WeixinConsumerApplication.class);
}
}

View File

@ -0,0 +1,170 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.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 Group2Weixin extends GroupConnector {
private final static Logger logger = LoggerFactory.getLogger(Group2Weixin.class);
LdapUtils ldapUtils;
public Group2Weixin() {
}
@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;
}
}

View File

@ -0,0 +1,136 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.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 Organization2Weixin extends OrganizationConnector{
private final static Logger logger = LoggerFactory.getLogger(Organization2Weixin.class);
LdapUtils ldapUtils;
public Organization2Weixin() {
}
@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.getParentId()+"))", 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);
}
}

View File

@ -0,0 +1,62 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.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 Password2Weixin extends PasswordConnector{
private final static Logger logger = LoggerFactory.getLogger(Password2Weixin.class);
LdapUtils ldapUtils;
public Password2Weixin() {
}
@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;
}
}

View File

@ -0,0 +1,157 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.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 UserInfo2Weixin extends UserInfoConnector{
private final static Logger logger = LoggerFactory.getLogger(UserInfo2Weixin.class);
LdapUtils ldapUtils;
public UserInfo2Weixin() {
}
@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;
}
}

View File

@ -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=LdapConsumerGroup
# 是否自动提交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

View File

@ -13,11 +13,6 @@
</attributes> </attributes>
</classpathentry> </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.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.web.container"/> <classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer">
<attributes>
<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="bin/default"/> <classpathentry kind="output" path="bin/default"/>
</classpath> </classpath>

View File

@ -17,6 +17,11 @@
<arguments> <arguments>
</arguments> </arguments>
</buildCommand> </buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand> <buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name> <name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments> <arguments>
@ -27,11 +32,6 @@
<arguments> <arguments>
</arguments> </arguments>
</buildCommand> </buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec> </buildSpec>
<natures> <natures>
<nature>org.eclipse.jdt.core.javanature</nature> <nature>org.eclipse.jdt.core.javanature</nature>

View File

@ -3,16 +3,16 @@ description = "maxkey-web-manage"
// Apply the java plugin to add support for Java // Apply the java plugin to add support for Java
apply plugin: 'java' apply plugin: 'java'
//apply plugin: 'war' //apply plugin: 'war'
apply plugin: 'eclipse-wtp' //apply plugin: 'eclipse-wtp'
apply plugin: 'com.bmuschko.tomcat-base' //apply plugin: 'com.bmuschko.tomcat-base'
apply plugin: 'com.bmuschko.tomcat' //apply plugin: 'com.bmuschko.tomcat'
buildscript { buildscript {
repositories { repositories {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath "com.bmuschko:gradle-tomcat-plugin:2.2.3" //classpath "com.bmuschko:gradle-tomcat-plugin:2.2.3"
} }
} }
@ -28,6 +28,7 @@ dependencies {
} }
/*
eclipse { eclipse {
wtp { wtp {
@ -39,4 +40,4 @@ eclipse {
} }
} }
} }*/

View File

@ -20,11 +20,6 @@
</attributes> </attributes>
</classpathentry> </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.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.web.container"/> <classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer">
<attributes>
<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="bin/default"/> <classpathentry kind="output" path="bin/default"/>
</classpath> </classpath>

View File

@ -23,6 +23,11 @@
<arguments> <arguments>
</arguments> </arguments>
</buildCommand> </buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand> <buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name> <name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments> <arguments>
@ -33,11 +38,6 @@
<arguments> <arguments>
</arguments> </arguments>
</buildCommand> </buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec> </buildSpec>
<natures> <natures>
<nature>org.eclipse.jdt.core.javanature</nature> <nature>org.eclipse.jdt.core.javanature</nature>

View File

@ -3,16 +3,16 @@ description = "maxkey-web-maxkey"
// Apply the java plugin to add support for Java // Apply the java plugin to add support for Java
apply plugin: 'java' apply plugin: 'java'
//apply plugin: 'war' //apply plugin: 'war'
apply plugin: 'eclipse-wtp' //apply plugin: 'eclipse-wtp'
apply plugin: 'com.bmuschko.tomcat-base' //apply plugin: 'com.bmuschko.tomcat-base'
apply plugin: 'com.bmuschko.tomcat' //apply plugin: 'com.bmuschko.tomcat'
buildscript { buildscript {
repositories { repositories {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath "com.bmuschko:gradle-tomcat-plugin:2.2.3" //classpath "com.bmuschko:gradle-tomcat-plugin:2.2.3"
} }
} }
dependencies { dependencies {
@ -34,7 +34,7 @@ dependencies {
compile project(":maxkey-identitys:maxkey-identity-kafka") compile project(":maxkey-identitys:maxkey-identity-kafka")
} }
/*
//For Eclipse IDE only //For Eclipse IDE only
eclipse { eclipse {
@ -53,4 +53,4 @@ tomcat {
httpPort = 80 httpPort = 80
contextPath = '/maxkey' contextPath = '/maxkey'
} }*/

View File

@ -17,8 +17,18 @@ include 'maxkey-identitys:maxkey-identity-rest'
//connectors //connectors
include 'maxkey-connectors:maxkey-connector-base' include 'maxkey-connectors:maxkey-connector-base'
include 'maxkey-connectors:maxkey-connector-ldap' //MS Active Directory
include 'maxkey-connectors:maxkey-connector-activedirectory' include 'maxkey-connectors:maxkey-connector-activedirectory'
//OpenLDAP
include 'maxkey-connectors:maxkey-connector-ldap'
//
include 'maxkey-connectors:maxkey-connector-workweixin'
//
include 'maxkey-connectors:maxkey-connector-dingding'
//
include 'maxkey-connectors:maxkey-connector-feishu'
//WeLink
include 'maxkey-connectors:maxkey-connector-welink'
//Protocol //Protocol
//include 'maxkey-protocols' //include 'maxkey-protocols'

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long