package org.apereo.cas.adaptors.ldap.services;
import com.google.common.base.Throwables;
import org.apereo.cas.configuration.model.support.ldap.serviceregistry.LdapServiceRegistryProperties;
import org.apereo.cas.services.AbstractRegisteredService;
import org.apereo.cas.services.RegisteredService;
import org.apereo.cas.util.LdapUtils;
import org.apereo.cas.util.serialization.StringSerializer;
import org.apereo.cas.util.services.RegisteredServiceJsonSerializer;
import org.ldaptive.LdapAttribute;
import org.ldaptive.LdapEntry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
/**
* Default implementation of {@link LdapRegisteredServiceMapper} that is able
* to map ldap entries to {@link RegisteredService} instances based on
* certain attributes names. This implementation also respects the object class
* attribute of LDAP entries via {@link LdapUtils#OBJECTCLASS_ATTRIBUTE}.
*
* @author Misagh Moayyed
* @since 4.1.0
*/
public class DefaultLdapRegisteredServiceMapper implements LdapRegisteredServiceMapper {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLdapRegisteredServiceMapper.class);
private final LdapServiceRegistryProperties ldap;
private StringSerializer<RegisteredService> jsonSerializer = new RegisteredServiceJsonSerializer();
public DefaultLdapRegisteredServiceMapper(final LdapServiceRegistryProperties ldapProperties) {
ldap = ldapProperties;
}
@Override
public LdapEntry mapFromRegisteredService(final String dn, final RegisteredService svc) {
try {
if (svc.getId() == RegisteredService.INITIAL_IDENTIFIER_VALUE) {
((AbstractRegisteredService) svc).setId(System.currentTimeMillis());
}
final String newDn = getDnForRegisteredService(dn, svc);
LOGGER.debug("Creating entry [{}]", newDn);
final Collection<LdapAttribute> attrs = new ArrayList<>();
attrs.add(new LdapAttribute(ldap.getIdAttribute(), String.valueOf(svc.getId())));
final StringWriter writer = new StringWriter();
this.jsonSerializer.to(writer, svc);
attrs.add(new LdapAttribute(ldap.getServiceDefinitionAttribute(), writer.toString()));
attrs.add(new LdapAttribute(LdapUtils.OBJECTCLASS_ATTRIBUTE, "top", ldap.getObjectClass()));
return new LdapEntry(newDn, attrs);
} catch (final Exception e) {
throw Throwables.propagate(e);
}
}
@Override
public RegisteredService mapToRegisteredService(final LdapEntry entry) {
try {
final String value = LdapUtils.getString(entry, ldap.getServiceDefinitionAttribute());
if (StringUtils.hasText(value)) {
return this.jsonSerializer.from(value);
}
return null;
} catch (final Exception e) {
throw Throwables.propagate(e);
}
}
@Override
public String getObjectClass() {
return ldap.getObjectClass();
}
@Override
public String getIdAttribute() {
return ldap.getIdAttribute();
}
public void setJsonSerializer(final StringSerializer<RegisteredService> jsonSerializer) {
this.jsonSerializer = jsonSerializer;
}
@Override
public String getDnForRegisteredService(final String parentDn, final RegisteredService svc) {
return String.format("%s=%s,%s", ldap.getIdAttribute(), svc.getId(), parentDn);
}
}