Skip to content
Snippets Groups Projects
Commit 58db8298 authored by Teodor Caras's avatar Teodor Caras
Browse files

Allow the xwiki groups to be associated with organizational units and filters #83

parent f9076bb4
No related branches found
No related tags found
No related merge requests found
......@@ -21,6 +21,7 @@ package com.xwiki.ldapuserimport;
import java.util.List;
import java.util.Map;
import org.xwiki.component.annotation.Role;
/**
......@@ -116,7 +117,21 @@ public interface LDAPUserImportManager
* @throws Exception in case of exceptions
*/
Map<String, Map<String, String>> getLDAPGroups(String searchInput, String xWikiGroupName,
boolean isFullSearch) throws Exception;
boolean isFullSearch) throws Exception;
/**
* Get all the LDAP Organizational Units from a domain. Each group contains information about the relation with the
* current XWiki group (associated or not).
*
* @param searchInput the value to search for
* @param xWikiGroupName the group name
* @param isFullSearch allowing to choose if the search is a "contains" search or a "begin with" search
* @param isOUSearch denotes whether the search is done over LDAP groups or organizational units
* @return the list of organizational units
* @throws Exception in case of exceptions
*/
Map<String, Map<String, String>> getLDAPGroups(String searchInput, String xWikiGroupName,
boolean isFullSearch, boolean isOUSearch) throws Exception;
/**
* Associate a list of LDAP groups to an XWiki group.
......
......@@ -84,6 +84,8 @@ import static com.xwiki.ldapuserimport.internal.XWikiLDAPUtilsHelper.getXWikiLDA
@Singleton
public class DefaultLDAPUserImportManager implements LDAPUserImportManager
{
private static final String OU = "ou";
private static final String MEMBER = "member";
private static final String XWIKI_PREFERENCES = "XWikiPreferences";
......@@ -92,11 +94,14 @@ public class DefaultLDAPUserImportManager implements LDAPUserImportManager
private static final String USERNAME = "username";
private static final Map<String, String> DEFAULT_LDAP_FIELDS_MAPPING = new HashMap<String, String>() {{
private static final Map<String, String> DEFAULT_LDAP_FIELDS_MAPPING = new HashMap<String, String>()
{
{
put("first_name", "givenName");
put("last_name", "sn");
put("email", "mail");
}};
}
};
private static final String USER_PROFILE_KEY = "userProfile";
......@@ -147,8 +152,7 @@ public class DefaultLDAPUserImportManager implements LDAPUserImportManager
*/
@Override
public Map<String, Map<String, String>> getUsers(String singleField, String allFields,
String searchInput, boolean isFullSearch)
throws Exception
String searchInput, boolean isFullSearch) throws Exception
{
XWikiContext context = contextProvider.get();
String currentWikiId = context.getWikiId();
......@@ -546,7 +550,6 @@ public class DefaultLDAPUserImportManager implements LDAPUserImportManager
return membersCaseSensitive;
}
@Override
public boolean updateGroup(String xWikiGroupName) throws Exception
{
......@@ -613,7 +616,6 @@ public class DefaultLDAPUserImportManager implements LDAPUserImportManager
}
}
protected XWikiDocument getGroupDocument(String groupName, XWikiContext context) throws XWikiException
{
BaseClass groupClass = context.getWiki().getGroupClass(context);
......@@ -638,11 +640,10 @@ public class DefaultLDAPUserImportManager implements LDAPUserImportManager
} catch (Exception e) {
logger.error("Failed saving group [{}]", groupName, e);
}
}
protected void addUserToXWikiGroup(String xwikiUserName, XWikiDocument groupDoc,
String groupName, XWikiContext context)
String groupName, XWikiContext context)
{
try {
logger.debug("Adding user [{}] to xwiki group [{}]", xwikiUserName, groupName);
......@@ -669,8 +670,6 @@ public class DefaultLDAPUserImportManager implements LDAPUserImportManager
Map<String, String> map = new HashMap<>();
map.put(MEMBER, xwikiUserName);
groupClass.fromMap(map, memberObj);
}
logger.debug("Finished adding user [{}] to xwiki group [{}]", xwikiUserName, groupName);
} catch (Exception e) {
......@@ -767,7 +766,14 @@ public class DefaultLDAPUserImportManager implements LDAPUserImportManager
@Override
public Map<String, Map<String, String>> getLDAPGroups(String searchInput, String xWikiGroupName,
boolean isFullSearch) throws Exception
boolean isFullSearch) throws Exception
{
return getLDAPGroups(searchInput, xWikiGroupName, isFullSearch, false);
}
@Override
public Map<String, Map<String, String>> getLDAPGroups(String searchInput, String xWikiGroupName,
boolean isFullSearch, boolean isOUSearch) throws Exception
{
XWikiContext context = contextProvider.get();
String currentWikiId = context.getWikiId();
......@@ -781,15 +787,18 @@ public class DefaultLDAPUserImportManager implements LDAPUserImportManager
try {
connection.open(configuration.getLDAPBindDN(), configuration.getLDAPBindPassword(), context);
String filter = getGroupsFilter(searchInput, configuration, isFullSearch);
String filter = isOUSearch
? XWikiLDAPUtilsHelper.getSearchFilter("organizationalUnit", searchInput, new String[] { OU },
isFullSearch) : getGroupsFilter(searchInput, configuration, isFullSearch);
String base = configuration.getLDAPParam(LDAP_BASE_DN, "");
String[] attributeNameTable = new String[] {CN, "description"};
String[] attributeNameTable = new String[] { isOUSearch ? OU : CN, "description" };
PagedLDAPSearchResults result =
connection.searchPaginated(base, LDAPConnection.SCOPE_SUB, filter, attributeNameTable, false);
if (result.hasMore()) {
ldapGroups = getLDAPGroups(configuration, connection, result, context, xWikiGroupName, isFullSearch);
ldapGroups =
getLDAPGroups(configuration, connection, result, context, xWikiGroupName, isFullSearch, isOUSearch);
} else {
logger.warn("There are no result for base dn: [{}], search scope: [{}], filter: [{}], fields: [{}].",
base, LDAPConnection.SCOPE_SUB, filter, CN);
......@@ -809,9 +818,8 @@ public class DefaultLDAPUserImportManager implements LDAPUserImportManager
}
private Map<String, Map<String, String>> getLDAPGroups(XWikiLDAPConfig configuration,
XWikiLDAPConnection connection, PagedLDAPSearchResults result, XWikiContext context,
String xWikiGroupName, boolean isFullSearch)
throws Exception
XWikiLDAPConnection connection, PagedLDAPSearchResults result, XWikiContext context, String xWikiGroupName,
boolean isFullSearch, boolean isOUSearch) throws Exception
{
LDAPEntry resultEntry = null;
......@@ -825,7 +833,11 @@ public class DefaultLDAPUserImportManager implements LDAPUserImportManager
do {
Map<String, String> group =
getLDAPGroupDetails(connection, xWikiGroupName, resultEntry, ldapGroupMapping);
groupsMap.put(group.get(CN), group);
if (isOUSearch) {
groupsMap.put(group.get(OU), group);
} else {
groupsMap.put(group.get(CN), group);
}
hasMore = result.hasMore();
resultEntry = hasMore ? result.next() : null;
} while (resultEntry != null && groupsMap.size() < maxDisplayedUsersNb);
......
......@@ -182,6 +182,23 @@ public class LDAPUserImportScriptService implements ScriptService
return userImportManager.getLDAPGroups(searchInput, xWikiGroupName, isFullSearch);
}
/**
* Get all the LDAP groups from a domain. Each group contains information about the relation with the current XWiki
* group (associated or not).
*
* @param searchInput the value to search for
* @param xWikiGroupName the group name
* @param isFullSearch allowing to choose if the search is a "contains" search or a "begin with" search
* @param isOUSearch denotes whether the search should be done over LDAP groups or organizational units.
* @return the list of groups
* @throws Exception in case of exceptions
*/
public Map<String, Map<String, String>> getLDAPGroups(String searchInput,
String xWikiGroupName, boolean isFullSearch, boolean isOUSearch) throws Exception
{
return userImportManager.getLDAPGroups(searchInput, xWikiGroupName, isFullSearch, isOUSearch);
}
/**
* Associate a list of LDAP groups to an XWiki group.
*
......
......@@ -159,8 +159,8 @@
<jobName>LDAP Group Import Job</jobName>
</property>
<property>
<script>if (services.ldapuserimport.getConfiguration().getTriggerGroupImport() &amp;&amp; xcontext.isMainWiki()) {
services.ldapuserimport.importLDAPGroups()
<script>if (services.ldapuserimport.getConfiguration().getTriggerGroupImport() &amp;&amp; xcontext.isMainWiki()) {
services.ldapuserimport.importLDAPGroups()
}</script>
</property>
<property>
......
......@@ -74,18 +74,24 @@
#set ($message = $services.localization.render('importUsers.groupUpdate.updatingGroup.fail'))
#end
$jsontool.serialize({'message': $message})
#elseif ($request.action == 'getLDAPGroups')
#elseif ($request.action == 'getLDAPGroups' || $request.action == 'getLDAPOus')
#set ($noResultsMessage = $services.localization.render('importUsers.associateGroups.modal.fieldValue.noResults'))
#set ($isFullSearch = false)
#if ($request.searchType=="1")
#set ($isFullSearch = true)
#end
#set ($groups = $services.ldapuserimport.getLDAPGroups($request.searchInput, $request.xWikiGroupName, $isFullSearch))
#if ($request.action == 'getLDAPOus')
#set ($groups = $services.ldapuserimport.getLDAPGroups($request.searchInput, $request.xWikiGroupName, $isFullSearch, true))
#set ($idKey = 'ou')
#else
#set ($groups = $services.ldapuserimport.getLDAPGroups($request.searchInput, $request.xWikiGroupName, $isFullSearch))
#set ($idKey = 'cn')
#end
#foreach ($group in $groups.entrySet())
#if ($group.value.isAssociated == true)
#set ($message = $services.localization.render('importUsers.associateGroups.modal.alreadyAssociated', [$group.value.description, $group.value.cn]))
#set ($message = $services.localization.render('importUsers.associateGroups.modal.alreadyAssociated', [$group.value.description, $group.value.get($idKey)]))
#else
#set ($message = $services.localization.render('importUsers.associateGroups.modal.toAssociate', [$group.value.description, $group.value.cn]))
#set ($message = $services.localization.render('importUsers.associateGroups.modal.toAssociate', [$group.value.description, $group.value.get($idKey)]))
#end
#set ($group.value.displayMessage = $message)
#end
......
......@@ -42,8 +42,15 @@ importUsers.error.expand=Click to get more details about the error.
importUsers.error.invalidCSRF=Bad CSRF token, try to reload the page.
importUsers.modal.form.description=There are more results for this search. Please provide a more precise query.
importUsers.modal.field.label=Field to search in
importUsers.modal.fieldValue.label=Search text
importUsers.modal.fieldValue.search=Search
importUsers.modal.fieldValue.associationType.label=Association type
importUsers.modal.group.fieldValue.label=Search LDAP groups
importUsers.modal.group.fieldValue.placeholder=Type in the name of a group..
importUsers.modal.group.fieldValue.search=Search groups
importUsers.modal.ou.fieldValue.label=Search LDAP Organizational Units
importUsers.modal.ou.fieldValue.placeholder=Type in the name of an organizational unit..
importUsers.modal.ou.fieldValue.search=Search OUs
importUsers.modal.filter.fieldValue.label=LDAP Filter
importUsers.modal.filter.fieldValue.placeholder=Type in filter that will be associated to the group
importUsers.modal.fieldValue.noResults=No users were found for the searched value!
importUsers.modal.fieldValue.loadingResults=Loading results ...
importUsers.modal.fieldValue.importingResults=Importing users ...
......@@ -52,6 +59,9 @@ importUsers.modal.user.failedImport=Failed to import users!
importUsers.modal.user.alreadyImported={0} already imported in
importUsers.modal.user.created={0} user profile has been created in
importUsers.modal.user.toImport={0} to import in
importUsers.modal.group.search.type.group=LDAP Group
importUsers.modal.group.search.type.ou=LDAP Organizational Unit
importUsers.modal.group.search.type.filter=LDAP Filter
importUsers.modal.close=Close
admin.ldapuserimport=LDAP User Import
......@@ -97,7 +107,7 @@ importUsers.groupUpdate.updatingGroup.fail=Group update failed.
importUsers.associateGroups.title=Associate LDAP Group
importUsers.associateGroups.livetableActionButton=Associate
importUsers.associateGroups.livetableActionButton.hint=Associate this group with one or more LDAP groups to synchronize users from them.
importUsers.associateGroups.livetableActionButton.hint=Associate this group with one ore many LDAP groups to synchronize users from them.
importUsers.associateGroups.modal.alreadyAssociated={0} ({1}) is already assigned.
importUsers.associateGroups.modal.toAssociate={0} ({1})
importUsers.associateGroups.modal.associateButton=Associate
......
......@@ -723,6 +723,37 @@
var associateResultsLoading = $('#associateResultsLoading');
var associateButton = $('#associateButton');
$('#getFilterUsers input').on('change', function () {
$('#associatedFilter').val($(this).val());
});
$("#associationType").on('change', function () {
let selectedValue = $(this).val();
$(".associationType").each(function () {
if ($(this).attr('id') == selectedValue) {
$(this).removeClass('hidden');
$(this).find('input').prop('disabled', false);
} else {
$(this).addClass('hidden');
$(this).find('input').prop('disabled', true);
}
// Hide all possible search results done over different association types.
$('#ldapGroupSearchBox').addClass('hidden');
resultsContainer.addClass('hidden');
$('#ldapGroupSearchBox .infomessage').addClass('hidden');
$('#ldapGroupSearchBox .ldapError').addClass('hidden');
associateButton.addClass('hidden');
// Remove searches and selections done over different association types.
$('#groupsList').remove();
$('#associatedFilter').prop('disabled', true);
// Handle filter use case.
if (selectedValue == 'getFilterUsers') {
associateButton.removeClass('hidden');
$('#associatedFilter').prop('disabled', false);
}
});
});
// Set the XWiki group name in the associateLDAPGroups form
$('#groupstable').on('click', '.actionassociategroups', function() {
var xWikiGroupName = $(this).closest('tr').find('.name .group').data('reference');
......@@ -805,6 +836,7 @@
// Perform the groups association.
$('#associateLDAPGroups').submit(function(event) {
event.preventDefault();
$('#ldapGroupSearchBox').removeClass('hidden');
associateResultsLoading.removeClass('hidden');
resultsContainer.addClass('hidden');
var associateLDAPGroupsForm = $(this);
......@@ -1375,30 +1407,87 @@ ul#importedUsersList {
&lt;div class="hidden"&gt;
&lt;input type="hidden" name="form_token" value="$services.csrf.token"/&gt;
&lt;input type="hidden" name="outputSyntax" value="plain"/&gt;
&lt;input type="hidden" name="action" value="getLDAPGroups"/&gt;
&lt;input type="hidden" name="xWikiGroupName"/&gt;
&lt;/div&gt;
&lt;dl&gt;
&lt;dt&gt;
&lt;label for="searchInput"&gt;
$services.localization.render('importUsers.modal.fieldValue.label')
&lt;label for="associationType"&gt;
$services.localization.render('importUsers.modal.fieldValue.associationType.label')
&lt;/label&gt;
&lt;/dt&gt;
&lt;dd&gt;
&lt;input type="text" id="searchInput" name="searchInput" required
placeholder="$escapetool.xml($services.localization.render('importUsers.modal.fieldValue.search'))" /&gt;
&lt;/dd&gt;
&lt;dt&gt;
&lt;label for="searchType"&gt;
$services.localization.render('importUsers.modal.searchType.label')
&lt;/label&gt;
&lt;/dt&gt;
&lt;dd&gt;
&lt;input type="checkbox" id="searchType" name="searchType" value="1" /&gt;
&lt;select id="associationType" name="action"&gt;
&lt;option value="getLDAPGroups" selected&gt;$escapetool.xml($services.localization.render('importUsers.modal.group.search.type.group'))&lt;/option&gt;
&lt;option value="getLDAPOus"&gt;$escapetool.xml($services.localization.render('importUsers.modal.group.search.type.ou'))&lt;/option&gt;
&lt;option value="getFilterUsers"&gt;$escapetool.xml($services.localization.render('importUsers.modal.group.search.type.filter'))&lt;/option&gt;
&lt;/select&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;input type="submit" id="triggerGroupsSearch" class="btn btn-primary"
value="$services.localization.render('importUsers.modal.fieldValue.search')"/&gt;
&lt;div class="associationTypes"&gt;
&lt;div class="associationType" id="getLDAPGroups"&gt;
&lt;dl&gt;
&lt;dt&gt;
&lt;label for="searchInput"&gt;
$escapetool.xml($services.localization.render('importUsers.modal.group.fieldValue.label'))
&lt;/label&gt;
&lt;/dt&gt;
&lt;dd&gt;
&lt;input type="text" id="searchInput" name="searchInput" required
placeholder="$escapetool.xml($services.localization.render('importUsers.modal.group.fieldValue.placeholder'))" /&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;dl&gt;
&lt;dt&gt;
&lt;label for="searchType"&gt;
$escapetool.xml($services.localization.render('importUsers.modal.searchType.label'))
&lt;/label&gt;
&lt;/dt&gt;
&lt;dd&gt;
&lt;input type="checkbox" id="searchType" name="searchType" value="1" /&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;input type="submit" id="triggerGroupsSearch" class="btn btn-primary"
value="$escapetool.xml($services.localization.render('importUsers.modal.group.fieldValue.search'))"/&gt;
&lt;/div&gt;
&lt;div class="associationType hidden" id="getLDAPOus"&gt;
&lt;dl&gt;
&lt;dt&gt;
&lt;label for="searchInput"&gt;
$escapetool.xml($services.localization.render('importUsers.modal.ou.fieldValue.label'))
&lt;/label&gt;
&lt;/dt&gt;
&lt;dd&gt;
&lt;input disabled type="text" id="searchInput" name="searchInput" required
placeholder="$escapetool.xml($services.localization.render('importUsers.modal.ou.fieldValue.placeholder'))" /&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;dl&gt;
&lt;dt&gt;
&lt;label for="searchType"&gt;
$escapetool.xml($services.localization.render('importUsers.modal.searchType.label'))
&lt;/label&gt;
&lt;/dt&gt;
&lt;dd&gt;
&lt;input disabled type="checkbox" id="searchType" name="searchType" value="1" /&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;input disabled type="submit" id="triggerGroupsSearch" class="btn btn-primary"
value="$escapetool.xml($services.localization.render('importUsers.modal.ou.fieldValue.search'))"/&gt;
&lt;/div&gt;
&lt;div class="associationType hidden" id="getFilterUsers"&gt;
&lt;dl&gt;
&lt;dt&gt;
&lt;label for="searchInput"&gt;
$escapetool.xml($services.localization.render('importUsers.modal.filter.fieldValue.label'))
&lt;/label&gt;
&lt;/dt&gt;
&lt;dd&gt;
&lt;input disabled type="text" id="searchInput" name="searchInput" required
placeholder="$escapetool.xml($services.localization.render('importUsers.modal.filter.fieldValue.placeholder'))" /&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/form&gt;
&lt;form class="xform" id="associateLDAPGroups" action="$formAction"&gt;
&lt;div class="hidden"&gt;
......@@ -1406,6 +1495,7 @@ ul#importedUsersList {
&lt;input type="hidden" name="outputSyntax" value="plain"/&gt;
&lt;input type="hidden" name="action" value="associateGroups"/&gt;
&lt;input type="hidden" name="xWikiGroupName"/&gt;
&lt;input type="hidden" disabled id="associatedFilter" name="group"&gt;
&lt;/div&gt;
&lt;div class="box hidden" id="ldapGroupSearchBox"&gt;
&lt;div class="box infomessage hidden"&gt;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment

Consent

On this website, we use the web analytics service Matomo to analyze and review the use of our website. Through the collected statistics, we can improve our offerings and make them more appealing for you. Here, you can decide whether to allow us to process your data and set corresponding cookies for these purposes, in addition to technically necessary cookies. Further information on data protection—especially regarding "cookies" and "Matomo"—can be found in our privacy policy. You can withdraw your consent at any time.