package com.constellio.app.modules.es.connectors.ldap;
import static com.constellio.app.modules.es.connectors.ldap.ConnectorLDAPDocumentType.GROUP;
import static com.constellio.model.services.search.query.logical.LogicalSearchQueryOperators.where;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import com.constellio.app.modules.es.model.connectors.ConnectorDocument;
import com.constellio.app.modules.es.model.connectors.ldap.ConnectorLDAPInstance;
import com.constellio.app.modules.es.model.connectors.ldap.ConnectorLDAPUserDocument;
import com.constellio.app.modules.es.services.ESSchemasRecordsServices;
import com.constellio.model.entities.records.Record;
import com.constellio.model.entities.schemas.Metadata;
import com.constellio.model.entities.schemas.MetadataValueType;
import com.constellio.model.entities.structures.MapStringListStringStructure;
public class ConnectorLDAPCrawlerHelper {
private static final Logger LOGGER = LogManager.getLogger(ConnectorLDAPCrawlerHelper.class);
final ESSchemasRecordsServices esSchemas;
public ConnectorLDAPCrawlerHelper(ESSchemasRecordsServices esSchemas) {
this.esSchemas = esSchemas;
}
List<ConnectorDocument> wrapDocuments(ConnectorLDAPInstance connectorInstance, Map<String, LDAPObjectAttributes> ldapObjects,
ConnectorLDAPDocumentType documentType, String url) {
List<ConnectorDocument> returnList = new ArrayList<>();
for (Entry<String, LDAPObjectAttributes> ldapObject : ldapObjects.entrySet()) {
try {
returnList.add(wrapDocument(connectorInstance, ldapObject, documentType, url));
} catch (Exception e) {
LOGGER.error("document escaped " + ldapObject.getKey(), e);
}
}
return returnList;
}
ConnectorDocument wrapDocument(ConnectorLDAPInstance connectorInstance,
Entry<String, LDAPObjectAttributes> ldapObject,
ConnectorLDAPDocumentType documentType, String url) {
ConnectorDocument document = getOrCreateDocumentByDNAndUrl(ldapObject.getKey(), url, connectorInstance).setURL(url);
//Done by ConnectorEventObserver :
// document = populateMappedMetadas(document, connectorInstance, ldapObject.getValue());
switch (documentType) {
case USER:
ConnectorLDAPUserDocument returnDocument = (ConnectorLDAPUserDocument) ConnectorLDAPUserDocumentFactory
.populateUser((ConnectorLDAPUserDocument) document, ldapObject.getValue(), connectorInstance)
.setSearchable(true).setFetched(true).setManualTokens(Record.PUBLIC_TOKEN);
if (returnDocument.getDistinguishedName().equals(ldapObject.getKey())) {
return returnDocument.setTitle(returnDocument.getUsername());
} else {
throw new ConnectorLDAPCrawlerHelper_InvalidLDAPUserDN(ldapObject.getKey(),
returnDocument.getDistinguishedName());
}
default:
throw new RuntimeException("Unsupported type " + GROUP);
}
}
ConnectorDocument getOrCreateDocumentByDNAndUrl(String dn, String url, ConnectorLDAPInstance connectorInstance) {
List<ConnectorLDAPUserDocument> singleResult = esSchemas
.searchConnectorLDAPUserDocuments(where(esSchemas.connectorLdapUserDocument.distinguishedName()).is(dn)
.andWhere(esSchemas.connectorDocument.url()).is(url)
.andWhere(esSchemas.connectorDocument.connectorType()).is(connectorInstance.getConnectorType())
.andWhere(esSchemas.connectorDocument.connector()).is(connectorInstance.getId()));
if (singleResult.size() > 1) {
throw new RuntimeException(
"Distinguished name " + dn + " is not unique in connector instance " + connectorInstance.getId());
} else {
if (singleResult.isEmpty()) {
ConnectorLDAPUserDocument document = esSchemas.newConnectorLDAPUserDocument(connectorInstance);
return document.setDistinguishedName(dn);
} else {
return singleResult.get(0);
}
}
}
private ConnectorDocument populateMappedMetadas(ConnectorDocument document, ConnectorLDAPInstance connectorInstance,
LDAPObjectAttributes ldapObject) {
MapStringListStringStructure propertiesMapping = connectorInstance
.getPropertiesMapping();
for (Entry<String, List<String>> entry : propertiesMapping.entrySet()) {
String metadataName = entry.getKey();
Metadata metadata = esSchemas.getTypes().getMetadata(metadataName);
List<String> attributesNames = entry.getValue();
if (metadata.isMultivalue()) {
document.set(metadata.getLocalCode(), getMultiValues(attributesNames, ldapObject, metadata));
} else {
document.set(metadata.getLocalCode(), getSingleValue(attributesNames, ldapObject, metadata));
}
}
return document;
}
private Object getSingleValue(List<String> attributesNames, LDAPObjectAttributes ldapObject, Metadata metadata) {
if (attributesNames.size() > 1) {
throw new RuntimeException(
"Several values to populate a single value metadata " + StringUtils.join(attributesNames, "; ") + " :"
+ metadata.getCode());
}
MetadataValueType metadataType = metadata.getType();
switch (metadataType) {
case TEXT:
case STRING:
return ldapObject.get(attributesNames.get(0)).getStringValue();
default:
throw new RuntimeException("Unsupported " + metadataType);
}
}
private List<Object> getMultiValues(List<String> attributesNames, LDAPObjectAttributes ldapObject, Metadata metadata) {
List<Object> returnList = new ArrayList<>();
for (String attributeName : attributesNames) {
List<Object> value = ldapObject.get(attributeName).getValue();
if (value != null) {
returnList.addAll(value);
}
}
return returnList;
}
private class ConnectorLDAPCrawlerHelper_InvalidLDAPUserDN extends RuntimeException {
public ConnectorLDAPCrawlerHelper_InvalidLDAPUserDN(
String expectedValue, String actualValue) {
super("Expected value is " + expectedValue + " actual value " + actualValue);
}
}
}