/* * Copyright 2016 Red Hat, Inc. and/or its affiliates * and other contributors as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.keycloak.storage.ldap.mappers; import org.keycloak.component.ComponentModel; import org.keycloak.component.ComponentValidationException; import org.keycloak.models.KeycloakSession; import org.keycloak.models.LDAPConstants; import org.keycloak.models.RealmModel; import org.keycloak.provider.ProviderConfigProperty; import org.keycloak.provider.ProviderConfigurationBuilder; import org.keycloak.storage.UserStorageProvider; import org.keycloak.storage.ldap.LDAPConfig; import org.keycloak.storage.ldap.LDAPStorageProvider; import java.util.List; /** * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a> */ public class FullNameLDAPStorageMapperFactory extends AbstractLDAPStorageMapperFactory { public static final String PROVIDER_ID = "full-name-ldap-mapper"; protected static final List<ProviderConfigProperty> configProperties; static { configProperties = getConfigProps(null); } private static List<ProviderConfigProperty> getConfigProps(ComponentModel parent) { boolean readOnly = false; if (parent != null) { LDAPConfig config = new LDAPConfig(parent.getConfig()); readOnly = config.getEditMode() != UserStorageProvider.EditMode.WRITABLE; } return ProviderConfigurationBuilder.create() .property().name(FullNameLDAPStorageMapper.LDAP_FULL_NAME_ATTRIBUTE) .label("LDAP Full Name Attribute") .helpText("Name of LDAP attribute, which contains fullName of user. Usually it will be 'cn' ") .type(ProviderConfigProperty.STRING_TYPE) .defaultValue(LDAPConstants.CN) .add() .property().name(FullNameLDAPStorageMapper.READ_ONLY) .label("Read Only") .helpText("For Read-only is data imported from LDAP to Keycloak DB, but it's not saved back to LDAP when user is updated in Keycloak.") .type(ProviderConfigProperty.BOOLEAN_TYPE) .defaultValue(String.valueOf(readOnly)) .add() .property().name(FullNameLDAPStorageMapper.WRITE_ONLY) .label("Write Only") .helpText("For Write-only is data propagated to LDAP when user is created or updated in Keycloak. But this mapper is not used to propagate data from LDAP back into Keycloak. " + "This setting is useful if you configured separate firstName and lastName attribute mappers and you want to use those to read attribute from LDAP into Keycloak") .type(ProviderConfigProperty.BOOLEAN_TYPE) .defaultValue(String.valueOf(!readOnly)) .add() .build(); } @Override public String getHelpText() { return "Used to map full-name of user from single attribute in LDAP (usually 'cn' attribute) to firstName and lastName attributes of UserModel in Keycloak DB"; } @Override public List<ProviderConfigProperty> getConfigProperties() { return configProperties; } @Override public List<ProviderConfigProperty> getConfigProperties(RealmModel realm, ComponentModel parent) { return getConfigProps(parent); } @Override public String getId() { return PROVIDER_ID; } @Override public void validateConfiguration(KeycloakSession session, RealmModel realm, ComponentModel config) throws ComponentValidationException { checkMandatoryConfigAttribute(FullNameLDAPStorageMapper.LDAP_FULL_NAME_ATTRIBUTE, "LDAP Full Name Attribute", config); boolean readOnly = AbstractLDAPStorageMapper.parseBooleanParameter(config, FullNameLDAPStorageMapper.READ_ONLY); boolean writeOnly = AbstractLDAPStorageMapper.parseBooleanParameter(config, FullNameLDAPStorageMapper.WRITE_ONLY); ComponentModel parent = realm.getComponent(config.getParentId()); if (parent == null) { throw new ComponentValidationException("can't find parent component model"); } LDAPConfig cfg = new LDAPConfig(parent.getConfig()); UserStorageProvider.EditMode editMode = cfg.getEditMode(); if (writeOnly && cfg.getEditMode() != UserStorageProvider.EditMode.WRITABLE) { throw new ComponentValidationException("ldapErrorCantWriteOnlyForReadOnlyLdap"); } if (writeOnly && readOnly) { throw new ComponentValidationException("ldapErrorCantWriteOnlyAndReadOnly"); } } @Override protected AbstractLDAPStorageMapper createMapper(ComponentModel mapperModel, LDAPStorageProvider federationProvider) { return new FullNameLDAPStorageMapper(mapperModel, federationProvider); } }