/* * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.xwiki.social.authentication.internal; import java.util.Collections; import java.util.List; import java.util.Properties; import javax.inject.Inject; import org.apache.commons.lang.StringUtils; import org.xwiki.bridge.DocumentAccessBridge; import org.xwiki.component.annotation.Component; import org.xwiki.configuration.ConfigurationSource; import org.xwiki.context.Execution; import org.xwiki.model.EntityType; import org.xwiki.model.ModelConfiguration; import org.xwiki.model.ModelContext; import org.xwiki.model.reference.DocumentReference; import org.xwiki.model.reference.EntityReferenceValueProvider; import org.xwiki.model.reference.SpaceReference; import org.xwiki.model.reference.WikiReference; import com.xpn.xwiki.XWikiContext; @Component("socialAuthDocument") public class SocialAuthDocumentConfigurationSource implements ConfigurationSource { @Inject private Execution execution; @Inject private EntityReferenceValueProvider valueProvider; /** * @see #getDocumentAccessBridge() */ @Inject private DocumentAccessBridge documentAccessBridge; /** @see #getCurrentWikiReference() */ @Inject private ModelContext modelContext; /** @see #getCurrentWikiReference() */ @Inject private ModelConfiguration modelConfig; private static final String GLOBAL_CONFIGURATION_KEY = "xwiki.authentication.socialLogin.globalConfiguration"; private static final String IGNORE_PREFIX = "socialauth."; private static final String XWIKI_SPACE = "XWiki"; private static final String SOCIAL_LOGIN_CONFIGURATION_CLASS = "SocialLoginConfigurationClass"; private static final String SOCIAL_LOGIN_CONFIGURATION_DOCUMENT = "SocialLoginConfiguration"; /** * @return the XWiki Class reference of the XWiki Object containing the configuration properties */ protected DocumentReference getClassReference() { if (isGlobalConfiguration()) { return new DocumentReference(getMainWikiName(), XWIKI_SPACE, SOCIAL_LOGIN_CONFIGURATION_CLASS); } else { return new DocumentReference(SOCIAL_LOGIN_CONFIGURATION_CLASS, new SpaceReference(XWIKI_SPACE, getCurrentWikiReference())); } } /** * @return the document reference of the document containing an XWiki Object with configuration data or null if * there no such document in which case this configuration source will be skipped */ protected DocumentReference getDocumentReference() { if (isGlobalConfiguration()) { return new DocumentReference(getMainWikiName(), XWIKI_SPACE, SOCIAL_LOGIN_CONFIGURATION_DOCUMENT); } else { return new DocumentReference(SOCIAL_LOGIN_CONFIGURATION_DOCUMENT, new SpaceReference(XWIKI_SPACE, getCurrentWikiReference())); } } @Override public <T> T getProperty(String key) { // Remove the "socialauth." prefix when looking up key properties return this.getPropertyInternal(StringUtils.substringAfter(key, IGNORE_PREFIX)); } @Override public boolean containsKey(String key) { // Remove the "socialauth." prefix when looking up key properties return this.containsKeyInternal(StringUtils.substringAfter(key, IGNORE_PREFIX)); } private boolean isGlobalConfiguration() { String globalConfig = getContext().getWiki().Param(GLOBAL_CONFIGURATION_KEY); return "1".equals(globalConfig); } private XWikiContext getContext() { return (XWikiContext) this.execution.getContext().getProperty("xwikicontext"); } private String getMainWikiName() { String wikiName = valueProvider.getDefaultValue(EntityType.WIKI); return wikiName; } // ------------- // Re-implement AbstractDocumentConfigurationSource since it's internal and have changed several times public <T> T getPropertyInternal(String key) { return (T) getPropertyObject(key); } public boolean containsKeyInternal(String key) { return getPropertyObject(key) != null; } private Object getPropertyObject(String key) { Object result; DocumentReference documentReference = getFailsafeDocumentReference(); DocumentReference classReference = getFailsafeClassReference(); if (documentReference != null && classReference != null) { result = this.documentAccessBridge.getProperty(documentReference, classReference, key); } else { result = null; } return result; } @Override public boolean isEmpty() { return getKeys().isEmpty(); } private DocumentReference getFailsafeDocumentReference() { DocumentReference documentReference; try { documentReference = getDocumentReference(); } catch (Exception e) { // We verify that no error has happened and if one happened then we skip this configuration source. This // ensures the system will continue to work even if this source has a problem. documentReference = null; } return documentReference; } private DocumentReference getFailsafeClassReference() { DocumentReference classReference; try { classReference = getClassReference(); } catch (Exception e) { // We verify that no error has happened and if one happened then we skip this configuration source. This // ensures the system will continue to work even if this source has a problem. classReference = null; } return classReference; } /** * @return the reference pointing to the current wiki */ protected WikiReference getCurrentWikiReference() { if (this.modelContext.getCurrentEntityReference() != null) { return (WikiReference) this.modelContext.getCurrentEntityReference().extractReference(EntityType.WIKI); } return new WikiReference(this.modelConfig.getDefaultReferenceValue(EntityType.WIKI)); } @Override public List<String> getKeys() { return null; } @Override public <T> T getProperty(String key, T defaultValue) { T result = getProperty(key); if (result == null) { result = defaultValue; } return result; } @Override public <T> T getProperty(String key, Class<T> valueClass) { T result = getProperty(key); // Make sure we don't return null values for List and Properties (they must return empty elements // when using the typed API). if (result == null) { result = getDefault(valueClass); } return result; } /** * @param valueClass the class of the property * @param <T> the type of the property * @return the default value of a property for the provided class */ private <T> T getDefault(Class<T> valueClass) { T result = null; if (valueClass != null) { if (List.class.getName().equals(valueClass.getName())) { result = (T) Collections.emptyList(); } else if (Properties.class.getName().equals(valueClass.getName())) { result = (T) new Properties(); } } return result; } }