/*
* 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.platform.wiki.creationjob.script;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.xwiki.component.annotation.Component;
import org.xwiki.context.Execution;
import org.xwiki.extension.ExtensionId;
import org.xwiki.extension.distribution.internal.DistributionManager;
import org.xwiki.job.Job;
import org.xwiki.job.event.status.JobStatus;
import org.xwiki.model.reference.WikiReference;
import org.xwiki.platform.wiki.creationjob.WikiCreationRequest;
import org.xwiki.platform.wiki.creationjob.WikiCreator;
import org.xwiki.platform.wiki.creationjob.WikiCreationException;
import org.xwiki.script.service.ScriptService;
import org.xwiki.security.authorization.AccessDeniedException;
import org.xwiki.security.authorization.AuthorizationManager;
import org.xwiki.security.authorization.Right;
import org.xwiki.wiki.descriptor.WikiDescriptorManager;
import com.xpn.xwiki.XWikiContext;
/**
* Script services for the creation of wikis.
*
* @version $Id: cff08628458824ccf4b2c5e7882c2f78b748dc2d $
* @since 7.0M2
*/
@Component
@Singleton
@Named("wiki.creationjob")
public class WikiCreationJobScriptServices implements ScriptService
{
/**
* The key under which the last encountered error is stored in the current execution context.
*/
private static final String ERROR_KEY = "scriptservice.wikicreationjob.error";
@Inject
private WikiCreator wikiCreator;
@Inject
private Execution execution;
@Inject
private AuthorizationManager authorizationManager;
@Inject
private WikiDescriptorManager wikiDescriptorManager;
@Inject
private Provider<XWikiContext> xcontextProvider;
@Inject
private DistributionManager distributionManager;
@Inject
private Logger logger;
/**
* Asynchronously create a wiki.
*
* @param request creation wiki request containing all information about the wiki to create
* @return the creationjob that creates the wiki
*/
public Job createWiki(WikiCreationRequest request)
{
try {
// Verify that the user has the CREATE_WIKI right
XWikiContext xcontext = xcontextProvider.get();
WikiReference mainWikiReference = new WikiReference(wikiDescriptorManager.getMainWikiId());
authorizationManager.checkAccess(Right.CREATE_WIKI, xcontext.getUserReference(), mainWikiReference);
// Verify that if an extension id is provided, this extension is authorized.
if (request.getExtensionId() != null) {
if (!isAuthorizedExtension(request.getExtensionId())) {
throw new WikiCreationException(String.format("The extension [%s] is not authorized.",
request.getExtensionId()));
}
}
return wikiCreator.createWiki(request);
} catch (WikiCreationException e) {
setLastError(e);
logger.warn("Failed to create a new wiki.", e);
} catch (AccessDeniedException e) {
setLastError(e);
}
return null;
}
private boolean isAuthorizedExtension(ExtensionId extensionId)
{
ExtensionId defaultExtension = getDefaultWikiExtensionId();
if (defaultExtension != null && StringUtils.isNotBlank(defaultExtension.getId())) {
// For now, only the extension declared in the WAR is authorized
return defaultExtension.equals(extensionId);
} else {
// Unless there is nothing set, and so we allow everything
// TODO: work with flavor manager instead
return true;
}
}
/**
* @return the extension id of the default flavor
*/
public ExtensionId getDefaultWikiExtensionId()
{
return distributionManager.getWikiUIExtensionId();
}
/**
* @param wikiId id of the wiki
* @return the creationjob status corresponding to the creation of the wiki
*/
public JobStatus getJobStatus(String wikiId)
{
return wikiCreator.getJobStatus(wikiId);
}
/**
* @return a new request for the creation of a new wiki
*/
public WikiCreationRequest newWikiCreationRequest()
{
return new WikiCreationRequest();
}
/**
* Get the error generated while performing the previously called action.
* @return an eventual exception or {@code null} if no exception was thrown
* @since 1.1
*/
public Exception getLastError()
{
return (Exception) this.execution.getContext().getProperty(ERROR_KEY);
}
/**
* Store a caught exception in the context, so that it can be later retrieved using {@link #getLastError()}.
*
* @param e the exception to store, can be {@code null} to clear the previously stored exception
* @see #getLastError()
* @since 1.1
*/
private void setLastError(Exception e)
{
this.execution.getContext().setProperty(ERROR_KEY, e);
}
}