Merge branch 'DEVELOP' of ssh://git.eclipse.org:29418/openk-usermodules/org.eclipse.openk-usermodules.contactBaseData.backend into DEVELOP
diff --git a/src/main/java/org/eclipse/openk/contactbasedata/api/AuthNAuthApi.java b/src/main/java/org/eclipse/openk/contactbasedata/api/AuthNAuthApi.java
index ca7355c..9d79918 100644
--- a/src/main/java/org/eclipse/openk/contactbasedata/api/AuthNAuthApi.java
+++ b/src/main/java/org/eclipse/openk/contactbasedata/api/AuthNAuthApi.java
@@ -14,17 +14,23 @@
 */
 package org.eclipse.openk.contactbasedata.api;
 
+import org.eclipse.openk.contactbasedata.model.JwtToken;
 import org.eclipse.openk.contactbasedata.model.KeyCloakUser;
+import org.eclipse.openk.contactbasedata.model.LoginCredentials;
 import org.eclipse.openk.contactbasedata.viewmodel.UserModule;
 import org.springframework.cloud.openfeign.FeignClient;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
 
+import javax.xml.ws.Response;
 import java.util.List;
 
 @FeignClient(name = "${services.authNAuth.name}")
 public interface AuthNAuthApi {
 
+    @PostMapping( value="/portal/rest/beservice/login")
+    JwtToken login(@RequestBody LoginCredentials loginCredentials);
+
     @GetMapping(value= "/portal/rest/beservice/checkAuth")
     feign.Response isTokenValid(@RequestHeader("Authorization") String token );
 
diff --git a/src/main/java/org/eclipse/openk/contactbasedata/config/AuthNAuthSchedulerConfig.java b/src/main/java/org/eclipse/openk/contactbasedata/config/AuthNAuthSchedulerConfig.java
new file mode 100644
index 0000000..93f8125
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/contactbasedata/config/AuthNAuthSchedulerConfig.java
@@ -0,0 +1,37 @@
+package org.eclipse.openk.contactbasedata.config;
+
+import lombok.extern.log4j.Log4j2;
+import org.eclipse.openk.contactbasedata.service.AuthNAuthService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+
+@Log4j2
+@Configuration
+@EnableScheduling
+@ConditionalOnProperty(prefix = "authnauth-sync.scheduling", name="enabled", havingValue="true", matchIfMissing = false)
+public class AuthNAuthSchedulerConfig {
+
+    @Autowired
+    AuthNAuthService authNAuthService;
+
+    @Value("${authnauth-sync.scheduling.cron-expression}")
+    private String cronExpression;
+
+    @Bean
+    public void logConfigAuthNAuth(){
+        log.info("Scheduler is enabled with cron expression: " + cronExpression);
+    }
+
+    @Scheduled(cron = "${ldap-sync.scheduling.cron-expression}")
+    public void scheduleTaskSynchronize() {
+        log.info("Executing scheduled task: Synchronizing Users with AuthNAuth");
+        authNAuthService.synchronizeAuthNAuth();
+        log.info("Finished scheduled task: Synchronizing Users with AuthNAuth");
+    }
+
+}
diff --git a/src/main/java/org/eclipse/openk/contactbasedata/config/LdapSchedulerConfig.java b/src/main/java/org/eclipse/openk/contactbasedata/config/LdapSchedulerConfig.java
new file mode 100644
index 0000000..a3b3c78
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/contactbasedata/config/LdapSchedulerConfig.java
@@ -0,0 +1,38 @@
+package org.eclipse.openk.contactbasedata.config;
+
+import lombok.extern.log4j.Log4j2;
+import org.eclipse.openk.contactbasedata.service.LdapService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.scheduling.annotation.SchedulingConfigurer;
+import org.springframework.scheduling.config.ScheduledTaskRegistrar;
+
+@Log4j2
+@Configuration
+@EnableScheduling
+@ConditionalOnProperty(prefix = "ldap-sync.scheduling", name="enabled", havingValue="true", matchIfMissing = false)
+public class LdapSchedulerConfig {
+
+    @Autowired
+    LdapService ldapService;
+
+    @Value("${ldap-sync.scheduling.cron-expression}")
+    private String cronExpression;
+
+    @Bean
+    public void logConfigLdap(){
+        log.info("Scheduler is enabled with cron expression: " + cronExpression);
+    }
+
+    @Scheduled(cron = "${ldap-sync.scheduling.cron-expression}")
+    public void scheduleTaskSynchronize() {
+        log.info("Executing scheduled task: Synchronizing Users with Ldap");
+        ldapService.synchronizeLDAP();
+        log.info("Finished scheduled task: Synchronizing Users with Ldap");
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/contactbasedata/config/SchedulerConfig.java b/src/main/java/org/eclipse/openk/contactbasedata/config/SchedulerConfig.java
deleted file mode 100644
index 5440a66..0000000
--- a/src/main/java/org/eclipse/openk/contactbasedata/config/SchedulerConfig.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.eclipse.openk.contactbasedata.config;
-
-import lombok.extern.log4j.Log4j2;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.scheduling.annotation.EnableScheduling;
-
-@Log4j2
-@Configuration
-@EnableScheduling
-@ConditionalOnProperty(prefix = "ldap.scheduling", name="enabled", havingValue="true", matchIfMissing = false)
-public class SchedulerConfig {
-
-    @Value("${ldap.scheduling.cron-expression}")
-    private String cronExpression;
-
-    @Bean
-    public void logConfig(){
-        log.info("Scheduler is enabled with cron expression: " + cronExpression);
-    }
-
-}
diff --git a/src/main/java/org/eclipse/openk/contactbasedata/controller/AuthNAuthController.java b/src/main/java/org/eclipse/openk/contactbasedata/controller/AuthNAuthController.java
new file mode 100644
index 0000000..e69b82f
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/contactbasedata/controller/AuthNAuthController.java
@@ -0,0 +1,53 @@
+/*
+ *******************************************************************************
+ * Copyright (c) 2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************
+ */
+package org.eclipse.openk.contactbasedata.controller;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import lombok.extern.log4j.Log4j2;
+import org.eclipse.openk.contactbasedata.service.AuthNAuthService;
+import org.eclipse.openk.contactbasedata.service.LdapService;
+import org.eclipse.openk.contactbasedata.viewmodel.LdapUser;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.net.URISyntaxException;
+import java.util.List;
+
+@Log4j2
+@RestController
+@RequestMapping("/authnauth")
+public class AuthNAuthController {
+
+    @Autowired
+    private AuthNAuthService authNAuthService;
+
+    @ApiOperation(value = "Ermitteln der UserModules vom Auth'n'Auth-Service")
+    @ApiResponses(value = {@ApiResponse(code = 200, message = "Erfolgreich durchgeführt")})
+    @ResponseStatus(HttpStatus.OK)
+    @GetMapping( "/loginTest")
+    public ResponseEntity<Object> loginTest() throws URISyntaxException, JsonProcessingException {
+        authNAuthService.synchronizeAuthNAuth();
+        return ResponseEntity.ok().build();
+    }
+
+}
diff --git a/src/main/java/org/eclipse/openk/contactbasedata/model/JwtToken.java b/src/main/java/org/eclipse/openk/contactbasedata/model/JwtToken.java
new file mode 100644
index 0000000..193a11d
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/contactbasedata/model/JwtToken.java
@@ -0,0 +1,24 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+package org.eclipse.openk.contactbasedata.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class JwtToken {
+
+    @JsonProperty("access_token")
+    private String accessToken;
+
+    public String getAccessToken() { return accessToken; }
+    public void setAccessToken(String accessToken) { this.accessToken = accessToken; }
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/eclipse/openk/contactbasedata/model/LoginCredentials.java b/src/main/java/org/eclipse/openk/contactbasedata/model/LoginCredentials.java
new file mode 100644
index 0000000..223831f
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/contactbasedata/model/LoginCredentials.java
@@ -0,0 +1,41 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+package org.eclipse.openk.contactbasedata.model;
+
+public class LoginCredentials {
+    private String userName;
+    private String password;
+
+    public LoginCredentials() {
+    }
+
+    public LoginCredentials(String userName, String password) {
+        this.userName = userName;
+        this.password = password;
+    }
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/contactbasedata/repository/InternalPersonRepository.java b/src/main/java/org/eclipse/openk/contactbasedata/repository/InternalPersonRepository.java
index 1ea4525..b29aa5e 100644
--- a/src/main/java/org/eclipse/openk/contactbasedata/repository/InternalPersonRepository.java
+++ b/src/main/java/org/eclipse/openk/contactbasedata/repository/InternalPersonRepository.java
@@ -39,4 +39,6 @@
     Page<TblInternalPerson> findByContact_anonymizedFalseOrContact_anonymizedIsNull(Pageable pageable); // NOSONAR fd 07.02.2020: Method name cannot be changed
 
     List<TblInternalPerson> findByUidNotNull();
+
+    List<TblInternalPerson> findByUserRefNotNull();
 }
diff --git a/src/main/java/org/eclipse/openk/contactbasedata/service/AuthNAuthService.java b/src/main/java/org/eclipse/openk/contactbasedata/service/AuthNAuthService.java
new file mode 100644
index 0000000..746a8ee
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/contactbasedata/service/AuthNAuthService.java
@@ -0,0 +1,109 @@
+package org.eclipse.openk.contactbasedata.service;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectReader;
+import feign.Response;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang.StringUtils;
+import org.eclipse.openk.contactbasedata.api.AuthNAuthApi;
+import org.eclipse.openk.contactbasedata.exceptions.NotFoundException;
+import org.eclipse.openk.contactbasedata.model.*;
+import org.eclipse.openk.contactbasedata.repository.CommunicationRepository;
+import org.eclipse.openk.contactbasedata.repository.CommunicationTypeRepository;
+import org.eclipse.openk.contactbasedata.repository.InternalPersonRepository;
+import org.eclipse.openk.contactbasedata.service.util.LdapUserAttributesMapper;
+import org.eclipse.openk.contactbasedata.viewmodel.LdapUser;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.ResponseEntity;
+import org.springframework.ldap.core.LdapTemplate;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.client.RestTemplate;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import static org.springframework.ldap.query.LdapQueryBuilder.query;
+
+@Log4j2
+@Service
+public class AuthNAuthService {
+
+    @Value("${authnauth-sync.technical-username}")
+    private String technicalUsername;
+
+    @Value("${authnauth-sync.technical-userpassword}")
+    private String technicalUserPassword;
+
+    @Autowired
+    private InternalPersonRepository internalPersonRepository;
+
+    @Autowired
+    AuthNAuthApi authNAuthApi;
+
+    public List<KeyCloakUser> getKeycloakUsersWithTechnicalLogin() {
+        LoginCredentials loginCredentials = new LoginCredentials(technicalUsername, technicalUserPassword);
+        JwtToken jwtToken = authNAuthApi.login(loginCredentials);
+        List<KeyCloakUser> keycloakUsers = authNAuthApi.getKeycloakUsers(jwtToken.getAccessToken());
+        authNAuthApi.logout(jwtToken.getAccessToken());
+        return keycloakUsers;
+    }
+
+    @Transactional
+    public void synchronizeAuthNAuth() {
+        List<KeyCloakUser> keycloakUsers = getKeycloakUsersWithTechnicalLogin();
+        List<TblInternalPerson> internalPersonList = internalPersonRepository.findByUserRefNotNull();
+
+        Map<String, KeyCloakUser> userRefToKeycloakMap = keycloakUsers.stream().collect(
+                Collectors.toMap(KeyCloakUser::getUsername, Function.identity()));
+
+        List<TblInternalPerson> internalPersonListSynchronized = getTblInternalPersonSynchronized(internalPersonList, userRefToKeycloakMap);
+
+        //Update all Users with the synchronized KeyCloak data
+        internalPersonRepository.saveAll(internalPersonListSynchronized);
+
+        log.info("Synchronization changed data of: " + internalPersonListSynchronized.size() + " internal user/s");
+        log.info("Attribute/s of the following internal user/s were updated:");
+        for (TblInternalPerson tblInternalPerson : internalPersonListSynchronized) {
+            log.info("Id: " + tblInternalPerson.getId() + " Firstname: " + tblInternalPerson.getFirstName() + " Lastname: " + tblInternalPerson.getLastName());
+        }
+
+    }
+
+    private List<TblInternalPerson> getTblInternalPersonSynchronized(List<TblInternalPerson> internalPersonList, Map<String, KeyCloakUser> userRefToKeycloakMap) {
+        List<TblInternalPerson> internalPersonListSynchronized = new ArrayList<>();
+
+        for (TblInternalPerson tblInternalPerson : internalPersonList) {
+
+            KeyCloakUser keyCloakUserToSync = userRefToKeycloakMap.get(tblInternalPerson.getUserRef());
+            boolean attributesChanged = mapKeycloakUserToInternaPerson(tblInternalPerson, keyCloakUserToSync);
+
+            if (attributesChanged) {
+                internalPersonListSynchronized.add(tblInternalPerson);
+            }
+        }
+        return internalPersonListSynchronized;
+    }
+
+    private boolean mapKeycloakUserToInternaPerson(TblInternalPerson tblInternalPerson, KeyCloakUser keyCloakUserToSync) {
+        boolean attributesChanged = false;
+        if (keyCloakUserToSync == null) {
+            tblInternalPerson.setUserRef(null);
+            attributesChanged = true;
+        } else {
+            if (!Objects.equals(tblInternalPerson.getFirstName(), keyCloakUserToSync.getFirstName())
+                    || !Objects.equals(tblInternalPerson.getLastName(), keyCloakUserToSync.getLastName())) {
+                tblInternalPerson.setLastName(keyCloakUserToSync.getLastName());
+                tblInternalPerson.setFirstName(keyCloakUserToSync.getFirstName());
+                attributesChanged = true;
+            }
+        }
+        return attributesChanged;
+    }
+
+
+}
diff --git a/src/main/java/org/eclipse/openk/contactbasedata/service/LdapService.java b/src/main/java/org/eclipse/openk/contactbasedata/service/LdapService.java
index 8636830..cc67420 100644
--- a/src/main/java/org/eclipse/openk/contactbasedata/service/LdapService.java
+++ b/src/main/java/org/eclipse/openk/contactbasedata/service/LdapService.java
@@ -26,13 +26,13 @@
 @Service
 public class LdapService {
 
-    @Value("${ldap.attribute-mapping.uid}")
+    @Value("${ldap-sync.attribute-mapping.uid}")
     private String uid;
 
-    @Value("${ldap.db-id-mapping.telephone-number-id}")
+    @Value("${ldap-sync.db-id-mapping.telephone-number-id}")
     private Long telephoneNumberId;
 
-    @Value("${ldap.db-id-mapping.mail-id}")
+    @Value("${ldap-sync.db-id-mapping.mail-id}")
     private Long mailId;
 
     @Autowired
@@ -98,6 +98,12 @@
 
         //Update all found Users with the synchronized LDAP data
         internalPersonRepository.saveAll(internalPersonListSynchronized);
+
+        log.info("Synchronization changed data of: " + internalPersonListSynchronized.size() + " internal user/s");
+        log.info("Attribute/s of the following internal user/s were updated:");
+        for (TblInternalPerson tblInternalPerson : internalPersonListSynchronized) {
+            log.info("Id: " + tblInternalPerson.getId() + " Firstname: " + tblInternalPerson.getFirstName() + " Lastname: " + tblInternalPerson.getLastName());
+        }
     }
 
     private RefCommunicationType getRefCommunicationType(Long refCommunicationTypeId) {
diff --git a/src/main/java/org/eclipse/openk/contactbasedata/service/SchedulingService.java b/src/main/java/org/eclipse/openk/contactbasedata/service/SchedulingService.java
deleted file mode 100644
index 1ffa3c5..0000000
--- a/src/main/java/org/eclipse/openk/contactbasedata/service/SchedulingService.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.eclipse.openk.contactbasedata.service;
-
-import lombok.extern.log4j.Log4j2;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Service;
-
-@Log4j2
-@Service
-public class SchedulingService {
-
-    @Autowired
-    LdapService ldapService;
-
-    @Scheduled(cron = "${ldap.scheduling.cron-expression}")
-    public void scheduleTaskSynchronize() {
-        log.info("Executing scheduled task: Synchronizing Users");
-        ldapService.synchronizeLDAP();
-        log.info("Finished scheduled task: Synchronizing Users");
-    }
-}
diff --git a/src/main/java/org/eclipse/openk/contactbasedata/service/util/LdapUserAttributesMapper.java b/src/main/java/org/eclipse/openk/contactbasedata/service/util/LdapUserAttributesMapper.java
index e856921..3827a14 100644
--- a/src/main/java/org/eclipse/openk/contactbasedata/service/util/LdapUserAttributesMapper.java
+++ b/src/main/java/org/eclipse/openk/contactbasedata/service/util/LdapUserAttributesMapper.java
@@ -29,28 +29,28 @@
     ----------------------
     */
 
-    @Value("${ldap.attribute-mapping.uid}")
+    @Value("${ldap-sync.attribute-mapping.uid}")
     private String uid;
 
-    @Value("${ldap.attribute-mapping.fullname}")
+    @Value("${ldap-sync.attribute-mapping.fullname}")
     private String fullname;
 
-    @Value("${ldap.attribute-mapping.lastname}")
+    @Value("${ldap-sync.attribute-mapping.lastname}")
     private String lastname;
 
-    @Value("${ldap.attribute-mapping.firstname}")
+    @Value("${ldap-sync.attribute-mapping.firstname}")
     private String firstname;
 
-    @Value("${ldap.attribute-mapping.title}")
+    @Value("${ldap-sync.attribute-mapping.title}")
     private String title;
 
-    @Value("${ldap.attribute-mapping.department}")
+    @Value("${ldap-sync.attribute-mapping.department}")
     private String department;
 
-    @Value("${ldap.attribute-mapping.mail}")
+    @Value("${ldap-sync.attribute-mapping.mail}")
     private String mail;
 
-    @Value("${ldap.attribute-mapping.telephone-number}")
+    @Value("${ldap-sync.attribute-mapping.telephone-number}")
     private String telephoneNumber;
 
     @Override
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 9029383..0c70ee9 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -24,7 +24,7 @@
     port: 10389
     urls: ldap://entopkon:10389
 
-ldap:
+ldap-sync:
   attribute-mapping:
     uid: uid
     fullname: cn
@@ -38,8 +38,18 @@
     mail-id: 1
     telephone-number-id: 2
   scheduling:
+    enabled: true
+    cron-expression: '*/10 * * * * *'
+
+authnauth-sync:
+  attribute-mapping:
+    lastname: true
+    firstname: true
+  scheduling:
     enabled: false
     cron-expression: '*/10 * * * * *'
+  technical-userpassword: admin
+  technical-username: admin
 
 server:
   max-http-header-size: 262144