TSK-1723: Synchronization of LDAP data for users

This commit is contained in:
Joerg Heffner 2021-09-21 09:23:26 +02:00 committed by gitgoodjhe
parent 2bf90fd0fe
commit e033f35cdc
22 changed files with 494 additions and 2 deletions

View File

@ -93,6 +93,13 @@ objectclass: person
objectclass: top
givenName: Titus
description: desc
phoneNumber: 012345678
mobileNumber: 09876554321
email: Titus.Toll@taskana.de
orgLevel1: ABC
orgLevel2: DEF/GHI
someDepartement: JKL
orgLevel4: MNO/PQR
memberOf: cn=Organisationseinheit KSC 1,cn=Organisationseinheit KSC,cn=organisation,OU=Test,O=TASKANA
memberOf: cn=monitor-users,cn=groups,OU=Test,O=TASKANA
memberOf: cn=business-admins,cn=groups,OU=Test,O=TASKANA

View File

@ -13,6 +13,13 @@ taskana.ldap.userSearchFilterValue=person
taskana.ldap.userFirstnameAttribute=givenName
taskana.ldap.userLastnameAttribute=sn
taskana.ldap.userFullnameAttribute=cn
taskana.ldap.userPhoneAttribute=phoneNumber
taskana.ldap.userMobilePhoneAttribute=mobileNumber
taskana.ldap.userEmailAttribute=email
taskana.ldap.userOrglevel1Attribute=orgLevel1
taskana.ldap.userOrglevel2Attribute=orgLevel2
taskana.ldap.userOrglevel3Attribute=someDepartement
taskana.ldap.userOrglevel4Attribute=orgLevel4
taskana.ldap.userIdAttribute=uid
taskana.ldap.userMemberOfGroupAttribute=memberOf
taskana.ldap.groupSearchBase=cn=groups

View File

@ -62,7 +62,11 @@ public class TaskanaEngineConfiguration {
private static final String TASKANA_JOB_PRIORITY_BATCHSIZE = "taskana.jobs.priority.batchSize";
private static final String TASKANA_JOB_PRIORITY_RUN_EVERY = "taskana.jobs.priority.runEvery";
private static final String TASKANA_JOB_PRIORITY_FIRST_RUN = "taskana.jobs.priority.firstRunAt";
private static final String TASKANA_JOB_USER_REFRESH_FIRST_RUN =
"taskana.jobs.user.refresh.firstRunAt";
private static final String TASKANA_JOB_PRIORITY_ACTIVE = "taskana.jobs.priority.active";
private static final String TASKANA_JOB_USER_REFRESH_RUN_EVERY =
"taskana.jobs.user.refresh.runEvery";
private static final String TASKANA_DOMAINS_PROPERTY = "taskana.domains";
private static final String TASKANA_CLASSIFICATION_TYPES_PROPERTY =
"taskana.classification.types";
@ -121,6 +125,9 @@ public class TaskanaEngineConfiguration {
private Duration priorityJobRunEvery = Duration.parse("P1D");
private boolean priorityJobActive = false;
private Duration userRefreshJobRunEvery = Duration.parse("P1D");
private Instant userRefreshJobFirstRun = Instant.parse("2018-01-01T23:00:00Z");
public TaskanaEngineConfiguration(
DataSource dataSource, boolean useManagedTransactions, String schemaName) {
this(dataSource, useManagedTransactions, true, schemaName);
@ -419,6 +426,22 @@ public class TaskanaEngineConfiguration {
this.priorityJobRunEvery = priorityJobRunEvery;
}
public Duration getUserRefreshJobRunEvery() {
return userRefreshJobRunEvery;
}
public void setUserRefreshJobRunEvery(Duration userRefreshJobRunEvery) {
this.userRefreshJobRunEvery = userRefreshJobRunEvery;
}
public Instant getUserRefreshJobFirstRun() {
return userRefreshJobFirstRun;
}
public void setUserRefreshJobFirstRun(Instant userRefreshJobFirstRun) {
this.userRefreshJobFirstRun = userRefreshJobFirstRun;
}
public boolean isPriorityJobActive() {
return priorityJobActive;
}
@ -495,6 +518,12 @@ public class TaskanaEngineConfiguration {
parseProperty(props, TASKANA_JOB_PRIORITY_ACTIVE, Boolean::parseBoolean)
.ifPresent(this::setPriorityJobActive);
parseProperty(props, TASKANA_JOB_USER_REFRESH_RUN_EVERY, Duration::parse)
.ifPresent(this::setUserRefreshJobRunEvery);
parseProperty(props, TASKANA_JOB_USER_REFRESH_FIRST_RUN, Instant::parse)
.ifPresent(this::setUserRefreshJobFirstRun);
parseProperty(
props,
TASKANA_JOB_TASK_CLEANUP_ALL_COMPLETED_SAME_PARENT_BUSINESS,

View File

@ -67,6 +67,13 @@ taskana.ldap.userSearchFilterValue=person
taskana.ldap.userFirstnameAttribute=givenName
taskana.ldap.userLastnameAttribute=sn
taskana.ldap.userFullnameAttribute=cn
taskana.ldap.userPhoneAttribute=phoneNumber
taskana.ldap.userMobilePhoneAttribute=mobileNumber
taskana.ldap.userEmailAttribute=email
taskana.ldap.userOrglevel1Attribute=orgLevel1
taskana.ldap.userOrglevel2Attribute=orgLevel2
taskana.ldap.userOrglevel3Attribute=someDepartement
taskana.ldap.userOrglevel4Attribute=orgLevel4
taskana.ldap.userIdAttribute=uid
taskana.ldap.groupSearchBase=cn=groups
taskana.ldap.groupSearchFilterName=objectclass

View File

@ -45,6 +45,13 @@ taskana.ldap.userSearchFilterValue=person
taskana.ldap.userFirstnameAttribute=givenName
taskana.ldap.userLastnameAttribute=sn
taskana.ldap.userFullnameAttribute=cn
taskana.ldap.userPhoneAttribute=phoneNumber
taskana.ldap.userMobilePhoneAttribute=mobileNumber
taskana.ldap.userEmailAttribute=email
taskana.ldap.userOrglevel1Attribute=orgLevel1
taskana.ldap.userOrglevel2Attribute=orgLevel2
taskana.ldap.userOrglevel3Attribute=someDepartement
taskana.ldap.userOrglevel4Attribute=orgLevel4
taskana.ldap.userIdAttribute=uid
taskana.ldap.groupSearchBase=ou=groups
taskana.ldap.groupSearchFilterName=objectclass

View File

@ -70,6 +70,13 @@ taskana.ldap.userSearchFilterValue=person
taskana.ldap.userFirstnameAttribute=givenName
taskana.ldap.userLastnameAttribute=sn
taskana.ldap.userFullnameAttribute=cn
taskana.ldap.userPhoneAttribute=phoneNumber
taskana.ldap.userMobilePhoneAttribute=mobileNumber
taskana.ldap.userEmailAttribute=email
taskana.ldap.userOrglevel1Attribute=orgLevel1
taskana.ldap.userOrglevel2Attribute=orgLevel2
taskana.ldap.userOrglevel3Attribute=someDepartement
taskana.ldap.userOrglevel4Attribute=orgLevel4
taskana.ldap.userIdAttribute=uid
taskana.ldap.userMemberOfGroupAttribute=memberOf
taskana.ldap.groupSearchBase=

View File

@ -18,6 +18,8 @@ taskana.jobs.history.batchSize=50
taskana.jobs.history.cleanup.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.history.cleanup.minimumAge=P14D
taskana.jobs.history.cleanup.runEvery=P1D
taskana.jobs.user.refresh.runEvery=P1D
taskana.jobs.user.refresh.firstRunAt=2018-07-25T23:00:00Z
taskana.german.holidays.enabled=true
taskana.german.holidays.corpus-christi.enabled=true
taskana.historylogger.name=AUDIT

View File

@ -12,6 +12,7 @@ import pro.taskana.common.api.TaskanaEngine;
import pro.taskana.common.internal.jobs.JobRunner;
import pro.taskana.common.internal.transaction.TaskanaTransactionProvider;
import pro.taskana.task.internal.jobs.TaskCleanupJob;
import pro.taskana.user.jobs.UserInfoRefreshJob;
import pro.taskana.workbasket.internal.jobs.WorkbasketCleanupJob;
/** This class invokes the JobRunner periodically to schedule long running jobs. */
@ -35,6 +36,7 @@ public class JobScheduler {
ClassNotFoundException {
TaskCleanupJob.initializeSchedule(taskanaEngine);
WorkbasketCleanupJob.initializeSchedule(taskanaEngine);
UserInfoRefreshJob.initializeSchedule(taskanaEngine);
if (taskanaEngine.isHistoryEnabled()) {
Thread.currentThread()

View File

@ -88,6 +88,13 @@ objectclass: person
objectclass: top
givenName: Titus
description: desc
phoneNumber: 012345678
mobileNumber: 09876554321
email: Titus.Toll@taskana.de
orgLevel1: QWERT
orgLevel2: DEF/GHI
someDepartement: JKL
orgLevel4: MNO/PQR
memberOf: cn=Organisationseinheit KSC 1,cn=Organisationseinheit KSC,cn=organisation,OU=Test,O=TASKANA
memberOf: cn=monitor-users,cn=groups,OU=Test,O=TASKANA
memberOf: cn=business-admins,cn=groups,OU=Test,O=TASKANA

View File

@ -3,12 +3,16 @@ package pro.taskana.example.ldap;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import pro.taskana.common.rest.ldap.LdapClient;
import pro.taskana.common.rest.models.AccessIdRepresentationModel;
import pro.taskana.common.test.rest.TaskanaSpringBootTest;
import pro.taskana.user.api.models.User;
/** Test Ldap attachment. */
@TaskanaSpringBootTest
@ -48,4 +52,40 @@ class LdapTest {
String dn = ldapClient.searchDnForAccessId("user-2-2");
assertThat(dn).isEqualTo("uid=user-2-2,cn=users,ou=test,o=taskana");
}
@Test
void should_ReturnAllUsersInUserRoleWithCorrectAttributes() {
Map<String, User> users =
ldapClient.searchUsersInUserRole().stream()
.collect(Collectors.toMap(User::getId, Function.identity()));
assertThat(users).hasSize(8);
User teamlead1 = users.get("teamlead-1");
assertThat(teamlead1.getId()).isEqualTo("teamlead-1");
assertThat(teamlead1.getFirstName()).isEqualTo("Titus");
assertThat(teamlead1.getLastName()).isEqualTo("Toll");
assertThat(teamlead1.getFullName()).isEqualTo("Titus Toll");
assertThat(teamlead1.getEmail()).isEqualTo("Titus.Toll@taskana.de");
assertThat(teamlead1.getPhone()).isEqualTo("012345678");
assertThat(teamlead1.getMobilePhone()).isEqualTo("09876554321");
assertThat(teamlead1.getOrgLevel1()).isEqualTo("ABC");
assertThat(teamlead1.getOrgLevel2()).isEqualTo("DEF/GHI");
assertThat(teamlead1.getOrgLevel3()).isEqualTo("JKL");
assertThat(teamlead1.getOrgLevel4()).isEqualTo("MNO/PQR");
User user11 = users.get("user-1-1");
assertThat(user11.getId()).isEqualTo("user-1-1");
assertThat(user11.getFirstName()).isEqualTo("Max");
assertThat(user11.getLastName()).isEqualTo("Mustermann");
assertThat(user11.getFullName()).isEqualTo("Max Mustermann");
assertThat(user11.getEmail()).isNull();
assertThat(user11.getPhone()).isNull();
assertThat(user11.getMobilePhone()).isNull();
assertThat(user11.getOrgLevel1()).isNull();
assertThat(user11.getOrgLevel2()).isNull();
assertThat(user11.getOrgLevel3()).isNull();
assertThat(user11.getOrgLevel4()).isNull();
}
}

View File

@ -21,6 +21,13 @@ taskana.ldap.userSearchFilterValue=person
taskana.ldap.userFirstnameAttribute=givenName
taskana.ldap.userLastnameAttribute=sn
taskana.ldap.userFullnameAttribute=cn
taskana.ldap.userPhoneAttribute=phoneNumber
taskana.ldap.userMobilePhoneAttribute=mobileNumber
taskana.ldap.userEmailAttribute=email
taskana.ldap.userOrglevel1Attribute=orgLevel1
taskana.ldap.userOrglevel2Attribute=orgLevel2
taskana.ldap.userOrglevel3Attribute=someDepartement
taskana.ldap.userOrglevel4Attribute=orgLevel4
taskana.ldap.userIdAttribute=uid
taskana.ldap.userMemberOfGroupAttribute=memberOf
taskana.ldap.groupSearchBase=

View File

@ -21,6 +21,13 @@ taskana.ldap.userSearchFilterValue=person
taskana.ldap.userFirstnameAttribute=givenName
taskana.ldap.userLastnameAttribute=sn
taskana.ldap.userFullnameAttribute=cn
taskana.ldap.userPhoneAttribute=phoneNumber
taskana.ldap.userMobilePhoneAttribute=mobileNumber
taskana.ldap.userEmailAttribute=email
taskana.ldap.userOrglevel1Attribute=orgLevel1
taskana.ldap.userOrglevel2Attribute=orgLevel2
taskana.ldap.userOrglevel3Attribute=someDepartement
taskana.ldap.userOrglevel4Attribute=orgLevel4
taskana.ldap.userIdAttribute=uid
taskana.ldap.userMemberOfGroupAttribute=memberOf
taskana.ldap.groupSearchBase=cn=groups

View File

@ -18,6 +18,13 @@ taskana.ldap.userSearchFilterValue=person
taskana.ldap.userFirstnameAttribute=givenName
taskana.ldap.userLastnameAttribute=sn
taskana.ldap.userFullnameAttribute=cn
taskana.ldap.userPhoneAttribute=phoneNumber
taskana.ldap.userMobilePhoneAttribute=mobileNumber
taskana.ldap.userEmailAttribute=email
taskana.ldap.userOrglevel1Attribute=orgLevel1
taskana.ldap.userOrglevel2Attribute=orgLevel2
taskana.ldap.userOrglevel3Attribute=someDepartement
taskana.ldap.userOrglevel4Attribute=orgLevel4
taskana.ldap.userIdAttribute=uid
taskana.ldap.userMemberOfGroupAttribute=memberOf
taskana.ldap.groupSearchBase=

View File

@ -18,6 +18,13 @@ taskana.ldap.userSearchFilterValue=person
taskana.ldap.userFirstnameAttribute=givenName
taskana.ldap.userLastnameAttribute=sn
taskana.ldap.userFullnameAttribute=cn
taskana.ldap.userPhoneAttribute=phoneNumber
taskana.ldap.userMobilePhoneAttribute=mobileNumber
taskana.ldap.userEmailAttribute=email
taskana.ldap.userOrglevel1Attribute=orgLevel1
taskana.ldap.userOrglevel2Attribute=orgLevel2
taskana.ldap.userOrglevel3Attribute=someDepartement
taskana.ldap.userOrglevel4Attribute=orgLevel4
taskana.ldap.userIdAttribute=uid
taskana.ldap.userMemberOfGroupAttribute=memberOf
taskana.ldap.groupSearchBase=

View File

@ -29,6 +29,8 @@ import pro.taskana.common.api.TaskanaRole;
import pro.taskana.common.api.exceptions.InvalidArgumentException;
import pro.taskana.common.api.exceptions.SystemException;
import pro.taskana.common.rest.models.AccessIdRepresentationModel;
import pro.taskana.user.api.models.User;
import pro.taskana.user.internal.models.UserImpl;
/** Class for Ldap access. */
@Component
@ -128,6 +130,33 @@ public class LdapClient {
return accessIds;
}
public List<User> searchUsersInUserRole() {
Set<String> userGroupsOrUser = taskanaEngineConfiguration.getRoleMap().get(TaskanaRole.USER);
final OrFilter userOrGroupFilter = new OrFilter();
userGroupsOrUser.forEach(
userOrGroup -> {
userOrGroupFilter.or(new EqualsFilter(getUserMemberOfGroupAttribute(), userOrGroup));
userOrGroupFilter.or(new EqualsFilter(getUserIdAttribute(), userOrGroup));
});
final AndFilter andFilter = new AndFilter();
andFilter.and(userOrGroupFilter);
final List<User> users =
ldapTemplate.search(
getUserSearchBase(),
andFilter.encode(),
SearchControls.SUBTREE_SCOPE,
getLookUpUserInfoAttributesToReturn(),
new UserInfoContextMapper());
LOGGER.debug("exit from searchUsersInUserRole. Retrieved the following users: {}.", users);
return users;
}
public List<AccessIdRepresentationModel> searchUsersByNameOrAccessId(final String name)
throws InvalidArgumentException {
isInitOrFail();
@ -349,6 +378,34 @@ public class LdapClient {
return LdapSettings.TASKANA_LDAP_USER_LASTNAME_ATTRIBUTE.getValueFromEnv(env);
}
public String getUserPhoneAttribute() {
return LdapSettings.TASKANA_LDAP_USER_PHONE_ATTRIBUTE.getValueFromEnv(env);
}
public String getUserMobilePhoneAttribute() {
return LdapSettings.TASKANA_LDAP_USER_MOBILE_PHONE_ATTRIBUTE.getValueFromEnv(env);
}
public String getUserEmailAttribute() {
return LdapSettings.TASKANA_LDAP_USER_EMAIL_ATTRIBUTE.getValueFromEnv(env);
}
public String getUserOrgLevel1Attribute() {
return LdapSettings.TASKANA_LDAP_USER_ORG_LEVEL_1_ATTRIBUTE.getValueFromEnv(env);
}
public String getUserOrgLevel2Attribute() {
return LdapSettings.TASKANA_LDAP_USER_ORG_LEVEL_2_ATTRIBUTE.getValueFromEnv(env);
}
public String getUserOrgLevel3Attribute() {
return LdapSettings.TASKANA_LDAP_USER_ORG_LEVEL_3_ATTRIBUTE.getValueFromEnv(env);
}
public String getUserOrgLevel4Attribute() {
return LdapSettings.TASKANA_LDAP_USER_ORG_LEVEL_4_ATTRIBUTE.getValueFromEnv(env);
}
public String getUserIdAttribute() {
return LdapSettings.TASKANA_LDAP_USER_ID_ATTRIBUTE.getValueFromEnv(env);
}
@ -467,6 +524,22 @@ public class LdapClient {
};
}
String[] getLookUpUserInfoAttributesToReturn() {
return new String[] {
getUserIdAttribute(),
getUserFirstnameAttribute(),
getUserLastnameAttribute(),
getUserFullnameAttribute(),
getUserPhoneAttribute(),
getUserMobilePhoneAttribute(),
getUserEmailAttribute(),
getUserOrgLevel1Attribute(),
getUserOrgLevel2Attribute(),
getUserOrgLevel3Attribute(),
getUserOrgLevel4Attribute()
};
}
@PostConstruct
void init() {
minSearchForLength = calcMinSearchForLength(3);
@ -526,6 +599,28 @@ public class LdapClient {
}
}
/** Context Mapper for user info entries. */
class UserInfoContextMapper extends AbstractContextMapper<User> {
@Override
public User doMapFromContext(final DirContextOperations context) {
final User user = new UserImpl();
user.setId(context.getStringAttribute(getUserIdAttribute()));
user.setFirstName(context.getStringAttribute(getUserFirstnameAttribute()));
user.setLastName(context.getStringAttribute(getUserLastnameAttribute()));
user.setFullName(context.getStringAttribute(getUserFullnameAttribute()));
user.setPhone(context.getStringAttribute(getUserPhoneAttribute()));
user.setMobilePhone(context.getStringAttribute(getUserMobilePhoneAttribute()));
user.setEmail(context.getStringAttribute(getUserEmailAttribute()));
user.setOrgLevel1(context.getStringAttribute(getUserOrgLevel1Attribute()));
user.setOrgLevel2(context.getStringAttribute(getUserOrgLevel2Attribute()));
user.setOrgLevel3(context.getStringAttribute(getUserOrgLevel3Attribute()));
user.setOrgLevel4(context.getStringAttribute(getUserOrgLevel4Attribute()));
return user;
}
}
/** Context Mapper for user entries. */
class UserContextMapper extends AbstractContextMapper<AccessIdRepresentationModel> {

View File

@ -10,7 +10,14 @@ enum LdapSettings {
TASKANA_LDAP_USER_FIRSTNAME_ATTRIBUTE("taskana.ldap.userFirstnameAttribute"),
TASKANA_LDAP_USER_LASTNAME_ATTRIBUTE("taskana.ldap.userLastnameAttribute"),
TASKANA_LDAP_USER_FULLNAME_ATTRIBUTE("taskana.ldap.userFullnameAttribute"),
TASKANA_LDAP_USER_PHONE_ATTRIBUTE("taskana.ldap.userPhoneAttribute"),
TASKANA_LDAP_USER_MOBILE_PHONE_ATTRIBUTE("taskana.ldap.userMobilePhoneAttribute"),
TASKANA_LDAP_USER_EMAIL_ATTRIBUTE("taskana.ldap.userEmailAttribute"),
TASKANA_LDAP_USER_ID_ATTRIBUTE("taskana.ldap.userIdAttribute"),
TASKANA_LDAP_USER_ORG_LEVEL_1_ATTRIBUTE("taskana.ldap.userOrglevel1Attribute"),
TASKANA_LDAP_USER_ORG_LEVEL_2_ATTRIBUTE("taskana.ldap.userOrglevel2Attribute"),
TASKANA_LDAP_USER_ORG_LEVEL_3_ATTRIBUTE("taskana.ldap.userOrglevel3Attribute"),
TASKANA_LDAP_USER_ORG_LEVEL_4_ATTRIBUTE("taskana.ldap.userOrglevel4Attribute"),
TASKANA_LDAP_USER_MEMBER_OF_GROUP_ATTRIBUTE("taskana.ldap.userMemberOfGroupAttribute"),
TASKANA_LDAP_GROUP_SEARCH_BASE("taskana.ldap.groupSearchBase"),
TASKANA_LDAP_BASE_DN("taskana.ldap.baseDn"),

View File

@ -0,0 +1,19 @@
package pro.taskana.common.rest.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
@Component
public class ApplicationContextProvider {
private static ApplicationContext context;
public static ApplicationContext getApplicationContext() {
return context;
}
@Autowired
public void setContext(ApplicationContext context) {
ApplicationContextProvider.context = context;
}
}

View File

@ -0,0 +1,127 @@
package pro.taskana.user.jobs;
import java.sql.PreparedStatement;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pro.taskana.common.api.ScheduledJob;
import pro.taskana.common.api.TaskanaEngine;
import pro.taskana.common.api.exceptions.InvalidArgumentException;
import pro.taskana.common.api.exceptions.NotAuthorizedException;
import pro.taskana.common.api.exceptions.SystemException;
import pro.taskana.common.internal.JobServiceImpl;
import pro.taskana.common.internal.jobs.AbstractTaskanaJob;
import pro.taskana.common.internal.transaction.TaskanaTransactionProvider;
import pro.taskana.common.rest.ldap.LdapClient;
import pro.taskana.common.rest.util.ApplicationContextProvider;
import pro.taskana.task.internal.jobs.helper.SqlConnectionRunner;
import pro.taskana.user.api.exceptions.UserAlreadyExistException;
import pro.taskana.user.api.exceptions.UserNotFoundException;
import pro.taskana.user.api.models.User;
/** Job to refresh all user info after a period of time. */
public class UserInfoRefreshJob extends AbstractTaskanaJob {
private static final Logger LOGGER = LoggerFactory.getLogger(UserInfoRefreshJob.class);
private final SqlConnectionRunner sqlConnectionRunner;
public UserInfoRefreshJob(TaskanaEngine taskanaEngine) {
this(taskanaEngine, null, null);
}
public UserInfoRefreshJob(
TaskanaEngine taskanaEngine,
TaskanaTransactionProvider txProvider,
ScheduledJob scheduledJob) {
super(taskanaEngine, txProvider, scheduledJob, true);
runEvery = taskanaEngine.getConfiguration().getUserRefreshJobRunEvery();
firstRun = taskanaEngine.getConfiguration().getUserRefreshJobFirstRun();
sqlConnectionRunner = new SqlConnectionRunner(taskanaEngine);
}
/**
* Initializes the {@linkplain UserInfoRefreshJob} schedule. <br>
* All scheduled jobs are cancelled/deleted and a new one is scheduled.
*
* @param taskanaEngine the TASKANA engine.
*/
public static void initializeSchedule(TaskanaEngine taskanaEngine) {
JobServiceImpl jobService = (JobServiceImpl) taskanaEngine.getJobService();
UserInfoRefreshJob job = new UserInfoRefreshJob(taskanaEngine);
jobService.deleteJobs(job.getType());
job.scheduleNextJob();
}
@Override
protected String getType() {
return UserInfoRefreshJob.class.getName();
}
@Override
protected void execute() {
LOGGER.info("Running job to refresh all user info");
LdapClient ldapClient =
ApplicationContextProvider.getApplicationContext().getBean("ldapClient", LdapClient.class);
try {
List<User> users = ldapClient.searchUsersInUserRole();
addExistingConfigurationDataToUsers(users);
clearExistingUsers();
insertNewUsers(users);
LOGGER.info("Job to refresh all user info has finished.");
} catch (Exception e) {
throw new SystemException("Error while processing UserRefreshJob.", e);
}
}
private void clearExistingUsers() {
sqlConnectionRunner.runWithConnection(
connection -> {
String sql = "DELETE FROM USER_INFO";
PreparedStatement statement = connection.prepareStatement(sql);
statement.execute();
if (!connection.getAutoCommit()) {
connection.commit();
}
});
}
private void insertNewUsers(List<User> users) {
users.forEach(
user -> {
try {
taskanaEngineImpl.getUserService().createUser(user);
} catch (InvalidArgumentException
| NotAuthorizedException
| UserAlreadyExistException e) {
throw new SystemException("Caught Exception while trying to insert new User", e);
}
});
}
private void addExistingConfigurationDataToUsers(List<User> users) {
users.forEach(
user -> {
try {
user.setData(taskanaEngineImpl.getUserService().getUser(user.getId()).getData());
} catch (UserNotFoundException e) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(
String.format(
"Failed to fetch configuration data for User "
+ "with ID '%s' because it doesn't exist"),
user.getId());
}
}
});
}
}

View File

@ -177,7 +177,14 @@ class LdapClientTest {
{"taskana.ldap.userLastnameAttribute", "sn"},
{"taskana.ldap.userFirstnameAttribute", "givenName"},
{"taskana.ldap.userFullnameAttribute", "cn"},
{"taskana.ldap.userSearchFilterValue", "person"}
{"taskana.ldap.userSearchFilterValue", "person"},
{"taskana.ldap.userPhoneAttribute", "phoneNumber"},
{"taskana.ldap.userMobilePhoneAttribute", "mobileNumber"},
{"taskana.ldap.userEmailAttribute", "email"},
{"taskana.ldap.userOrglevel1Attribute", "orgLevel1"},
{"taskana.ldap.userOrglevel2Attribute", "orgLevel2"},
{"taskana.ldap.userOrglevel3Attribute", "orgLevel3"},
{"taskana.ldap.userOrglevel4Attribute", "orgLevel4"},
})
.forEach(
strings ->

View File

@ -0,0 +1,87 @@
package pro.taskana.user.jobs;
import static org.assertj.core.api.Assertions.assertThat;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import pro.taskana.common.api.TaskanaEngine;
import pro.taskana.common.rest.ldap.LdapClient;
import pro.taskana.common.test.rest.TaskanaSpringBootTest;
import pro.taskana.common.test.security.JaasExtension;
import pro.taskana.common.test.security.WithAccessId;
import pro.taskana.user.api.UserService;
import pro.taskana.user.api.models.User;
import pro.taskana.user.internal.models.UserImpl;
@TaskanaSpringBootTest
@ExtendWith(JaasExtension.class)
class UserInfoRefreshJobIntTest {
TaskanaEngine taskanaEngine;
UserService userService;
LdapClient ldapClient;
@Autowired
public UserInfoRefreshJobIntTest(
TaskanaEngine taskanaEngine, UserService userService, LdapClient ldapClient) {
this.taskanaEngine = taskanaEngine;
this.userService = userService;
this.ldapClient = ldapClient;
}
@Test
@WithAccessId(user = "businessadmin")
void should_RefreshUserInfo_When_UserInfoRefreshJobIsExecuted() throws Exception {
try (Connection connection = taskanaEngine.getConfiguration().getDatasource().getConnection()) {
List<User> users = getUsers(connection);
assertThat(users).hasSize(14);
UserInfoRefreshJob userInfoRefreshJob = new UserInfoRefreshJob(taskanaEngine);
userInfoRefreshJob.execute();
users = getUsers(connection);
List<User> ldapusers = ldapClient.searchUsersInUserRole();
assertThat(users).hasSize(6).hasSameSizeAs(ldapusers);
assertThat(users)
.usingElementComparatorIgnoringFields("longName", "data")
.containsExactlyElementsOf(ldapusers);
}
}
private List<User> getUsers(Connection connection) throws Exception {
List<User> users = new ArrayList<>();
Statement statement = connection.createStatement();
ResultSet rs = statement.executeQuery("SELECT * FROM " + connection.getSchema() + ".USER_INFO");
while (rs.next()) {
User ldapUser = new UserImpl();
ldapUser.setId(rs.getString("USER_ID"));
ldapUser.setFirstName(rs.getString("FIRST_NAME"));
ldapUser.setLastName(rs.getString("LASTNAME"));
ldapUser.setFullName(rs.getString("FULL_NAME"));
ldapUser.setLongName(rs.getString("LONG_NAME"));
ldapUser.setEmail(rs.getString("E_MAIL"));
ldapUser.setPhone(rs.getString("PHONE"));
ldapUser.setMobilePhone(rs.getString("MOBILE_PHONE"));
ldapUser.setOrgLevel4(rs.getString("ORG_LEVEL_4"));
ldapUser.setOrgLevel3(rs.getString("ORG_LEVEL_3"));
ldapUser.setOrgLevel2(rs.getString("ORG_LEVEL_2"));
ldapUser.setOrgLevel1(rs.getString("ORG_LEVEL_1"));
ldapUser.setData(rs.getString("DATA"));
users.add(ldapUser);
}
return users;
}
}

View File

@ -22,6 +22,13 @@ taskana.ldap.userSearchFilterValue=person
taskana.ldap.userFirstnameAttribute=givenName
taskana.ldap.userLastnameAttribute=sn
taskana.ldap.userFullnameAttribute=cn
taskana.ldap.userPhoneAttribute=phoneNumber
taskana.ldap.userMobilePhoneAttribute=mobileNumber
taskana.ldap.userEmailAttribute=email
taskana.ldap.userOrglevel1Attribute=orgLevel1
taskana.ldap.userOrglevel2Attribute=orgLevel2
taskana.ldap.userOrglevel3Attribute=someDepartement
taskana.ldap.userOrglevel4Attribute=orgLevel4
taskana.ldap.userIdAttribute=uid
taskana.ldap.userMemberOfGroupAttribute=memberOf
taskana.ldap.groupSearchBase=

View File

@ -1,4 +1,4 @@
taskana.roles.user=cn=ksc-users,cn=groups,OU=Test,O=TASKANA | teamlead-1 | teamlead-2 | user-1-1 | user-1-2 | user-2-1 | user-2-2 | user-b-1 | user-b-2
taskana.roles.user=cn=ksc-users,cn=groups,OU=Test,O=TASKANA | teamlead-1 | teamlead-2 | user-1-1
taskana.roles.admin=admin | uid=admin,cn=users,OU=Test,O=TASKANA
taskana.roles.businessadmin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.monitor=monitor | cn=monitor-users,cn=groups,OU=Test,O=TASKANA