Issue
I have a problem with setting my own constructor of LdapProperties witch will overwrite this created by application.properties. Authors of framework did the class without setters what imo would make the answer very simple. Could someone explain me how to do it in the right way? I don't know what I am doing wrong.
The standardAuthenticationUsers is a list and it was my primary problem. I couldn't implement list to app property by using List something. If I write for example #jmix.ldap.standardAuthenticationUsers = Dev1, admin - it works fine.
I was forced to create my own constructor of LdapProperties because of this.
LdapProperties:
@ConfigurationProperties(prefix = "jmix.ldap")
@ConstructorBinding
public class LdapProperties {
boolean enabled;
String userDetailsSource;
List<String> urls;
String baseDn;
String managerDn;
String managerPassword;
String userSearchBase;
String userSearchFilter;
String usernameAttribute;
String memberAttribute;
String groupRoleAttribute;
String groupSearchBase;
boolean groupSearchSubtree;
String groupSearchFilter;
//Active Directory
Boolean useActiveDirectoryConfiguration;
String activeDirectoryDomain;
String groupForSynchronization;
Boolean synchronizeRoleAssignments;
Boolean synchronizeUserOnLogin;
List<String> defaultRoles;
List<String> standardAuthenticationUsers;
public LdapProperties(@DefaultValue("true") boolean enabled,
@DefaultValue("app") String userDetailsSource,
List<String> urls,
String baseDn,
String managerDn,
String managerPassword,
@DefaultValue("") String userSearchBase,
String userSearchFilter,
@DefaultValue("uid") String usernameAttribute,
@DefaultValue("uniqueMember") String memberAttribute,
@DefaultValue("cn") String groupRoleAttribute,
@DefaultValue("") String groupSearchBase,
@DefaultValue("false") boolean groupSearchSubtree,
@DefaultValue("(uniqueMember={0})") String groupSearchFilter,
@DefaultValue("false") Boolean useActiveDirectoryConfiguration,
String activeDirectoryDomain,
String groupForSynchronization,
@DefaultValue("true") Boolean synchronizeRoleAssignments,
@DefaultValue("true") Boolean synchronizeUserOnLogin,
@Nullable List<String> defaultRoles,
@DefaultValue({"admin", "system"}) List<String> standardAuthenticationUsers) {
this.enabled = enabled;
this.userDetailsSource = userDetailsSource;
this.urls = urls;
this.baseDn = baseDn;
this.managerDn = managerDn;
this.managerPassword = managerPassword;
this.userSearchBase = userSearchBase;
this.userSearchFilter = userSearchFilter;
this.usernameAttribute = usernameAttribute;
this.memberAttribute = memberAttribute;
this.groupRoleAttribute = groupRoleAttribute;
this.groupSearchBase = groupSearchBase;
this.groupSearchSubtree = groupSearchSubtree;
this.groupSearchFilter = groupSearchFilter;
this.useActiveDirectoryConfiguration = useActiveDirectoryConfiguration;
this.activeDirectoryDomain = activeDirectoryDomain;
this.groupForSynchronization = groupForSynchronization;
this.synchronizeRoleAssignments = synchronizeRoleAssignments;
this.synchronizeUserOnLogin = synchronizeUserOnLogin;
this.defaultRoles = defaultRoles == null ? Collections.emptyList() : defaultRoles;
this.standardAuthenticationUsers = standardAuthenticationUsers;
}
public boolean isEnabled() {
return enabled;
}
public String getUserDetailsSource() {
return userDetailsSource;
}
public List<String> getUrls() {
return urls;
}
public String getBaseDn() {
return baseDn;
}
public String getManagerDn() {
return managerDn;
}
public String getManagerPassword() {
return managerPassword;
}
public String getUserSearchBase() {
return userSearchBase;
}
public String getUserSearchFilter() {
return userSearchFilter;
}
public String getUsernameAttribute() {
return usernameAttribute;
}
public String getMemberAttribute() {
return memberAttribute;
}
public String getGroupRoleAttribute() {
return groupRoleAttribute;
}
public String getGroupSearchBase() {
return groupSearchBase;
}
public boolean isGroupSearchSubtree() {
return groupSearchSubtree;
}
public String getGroupSearchFilter() {
return groupSearchFilter;
}
public String getActiveDirectoryDomain() {
return activeDirectoryDomain;
}
public Boolean getUseActiveDirectoryConfiguration() {
return useActiveDirectoryConfiguration;
}
public String getGroupForSynchronization() {
return groupForSynchronization;
}
public Boolean getSynchronizeRoleAssignments() {
return synchronizeRoleAssignments;
}
public Boolean getSynchronizeUserOnLogin() {
return synchronizeUserOnLogin;
}
public List<String> getDefaultRoles() {
return defaultRoles;
}
public List<String> getStandardAuthenticationUsers() {
return standardAuthenticationUsers;
}
}
UserDetailsServiceLdapUserDetailsMapper:
public class UserDetailsServiceLdapUserDetailsMapper implements UserDetailsContextMapper {
protected UserDetailsService userDetailsService;
protected LdapUserDetailsSynchronizationStrategy synchronizationStrategy;
protected LdapProperties ldapProperties;
[...]
@Autowired
public void setLdapProperties(LdapProperties ldapProperties) {
this.ldapProperties = ldapProperties;
}
What I wanted to do:
@Component("sample_MyUserSynchronizationStrategy")
public class UserDetailsServiceLdapUserDetailsMapperImpl extends UserDetailsServiceLdapUserDetailsMapper {
private EntityManagerFactory emf;
public List<User> getUserList() {
EntityManager em = emf.createEntityManager();
TypedQuery<User> query = em.createQuery("select u from User u where u.password is not null ", User.class);
return query.getResultList();
}
public List<String> standardAuthenticationUsers = getUserList().stream().map(User::getUsername).collect(Collectors.toList());
@Override
public void setLdapProperties(LdapProperties ldapProperties) {
super.setLdapProperties(new LdapProperties(true,
"app",
Collections.singletonList("ldap"),
"baseDn",
"managerDn",
"password",
"",
"(&(objectClass=user)(sAMAccountName={0}))",
"uid",
"uniqueMember",
"cn",
"",
false,
"(uniqueMember={0})",
true,
"ADDomain",
"",
false,
true,
Collections.singletonList("ui-minimal"),
standardAuthenticationUsers));
}
}
Solution
Ok, thanks to @madteapod I created code that works the way I wanted to.
@Autowired
LdapProperties ldapProperties;
@Autowired
EntityManagerFactory entityManagerFactory;
public void addAppUsersWithStandardAuth() {
EntityManager entityManager = entityManagerFactory.createEntityManager();
TypedQuery<User> query = entityManager.createQuery("select u from User u where u.domain is null", User.class);
List<String> getUserListToString = query.getResultList().stream()
.map(User::getUsername)
.collect(Collectors.toList());
if (!ldapProperties.getStandardAuthenticationUsers().equals(getUserListToString)) {
List<String> difference = getUserListToString.stream()
.filter(element -> !ldapProperties.getStandardAuthenticationUsers().contains(element))
.collect(Collectors.toList());
ldapProperties.getStandardAuthenticationUsers().addAll(difference);
System.out.println(ldapProperties.getStandardAuthenticationUsers());
}
}
Answered By - Marcin Böhm