Skip to content
Permalink
Browse files Browse the repository at this point in the history
XWIKI-19856: Macro execution as any user without programming rights t…
…hrough the context macro
  • Loading branch information
tmortagne committed Sep 9, 2022
1 parent 4f964c3 commit bd34ad6
Show file tree
Hide file tree
Showing 9 changed files with 421 additions and 300 deletions.
Expand Up @@ -31,6 +31,7 @@
import org.xwiki.model.reference.EntityReference;
import org.xwiki.rendering.async.internal.AsyncRendererConfiguration;
import org.xwiki.rendering.block.Block;
import org.xwiki.rendering.block.XDOM;
import org.xwiki.rendering.syntax.Syntax;
import org.xwiki.rendering.transformation.TransformationContext;

Expand All @@ -46,6 +47,8 @@ public class BlockAsyncRendererConfiguration extends AsyncRendererConfiguration

private Block block;

private XDOM xdom;

private boolean asyncAllowed;

private boolean cacheAllowed;
Expand All @@ -70,8 +73,12 @@ public class BlockAsyncRendererConfiguration extends AsyncRendererConfiguration
*/
public BlockAsyncRendererConfiguration(List<?> idElements, Block block)
{
this.id = new ArrayList<>(idElements.size());
addElements(idElements);
if (idElements != null) {
this.id = new ArrayList<>(idElements.size());
addElements(idElements);
} else {
this.id = new ArrayList<>();
}
this.block = block;

// Enabled by default
Expand Down Expand Up @@ -113,6 +120,28 @@ public Block getBlock()
return this.block;
}

/**
* @return the XDOM to use in the transformation context
* @since 14.8RC1
* @since 14.4.5
* @since 13.10.10
*/
public XDOM getXDOM()
{
return this.xdom;
}

/**
* @param xdom the XDOM to use in the transformation context
* @since 14.8RC1
* @since 14.4.5
* @since 13.10.10
*/
public void setXDOM(XDOM xdom)
{
this.xdom = xdom;
}

/**
* @return true if the execution should be asynchronous if possible
*/
Expand Down
Expand Up @@ -119,11 +119,9 @@ public Block execute(boolean async, boolean cached) throws RenderingException
block = PARSERUTILS.convertToInline(block, true);
}

// Create a XDOM instance for the transformation context
XDOM xdom;
if (block instanceof XDOM) {
xdom = (XDOM) block;
} else {
// Get the XDOM instance for the transformation context
XDOM xdom = this.configuration.getXDOM();
if (xdom == null) {
Block rootBlock = block.getRoot();

if (rootBlock instanceof XDOM) {
Expand Down
Expand Up @@ -37,7 +37,7 @@
<dependencies>
<dependency>
<groupId>org.xwiki.platform</groupId>
<artifactId>xwiki-platform-rendering-async-default</artifactId>
<artifactId>xwiki-platform-rendering-async-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
Expand All @@ -52,6 +52,12 @@
</dependency>

<!-- Testing dependencies -->
<dependency>
<groupId>org.xwiki.platform</groupId>
<artifactId>xwiki-platform-rendering-async-default</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.xwiki.rendering</groupId>
<artifactId>xwiki-rendering-syntax-xwiki21</artifactId>
Expand Down Expand Up @@ -81,24 +87,10 @@
<artifactId>javax.servlet-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mortbay.jasper</groupId>
<artifactId>apache-el</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<executions>
<execution>
<!-- Specify the "default" execution id so that the "blocker" one is always executed -->
<id>default</id>
<configuration>
<excludes>
org/xwiki/rendering/internal/macro/display/DisplayMacro.java
</excludes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,147 @@
/*
* 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.rendering.async.internal;

import java.util.List;

import javax.inject.Inject;

import org.xwiki.bridge.DocumentAccessBridge;
import org.xwiki.model.reference.DocumentReference;
import org.xwiki.model.reference.DocumentReferenceResolver;
import org.xwiki.rendering.async.internal.block.BlockAsyncRendererConfiguration;
import org.xwiki.rendering.async.internal.block.BlockAsyncRendererExecutor;
import org.xwiki.rendering.block.Block;
import org.xwiki.rendering.block.Block.Axes;
import org.xwiki.rendering.block.MacroBlock;
import org.xwiki.rendering.block.MetaDataBlock;
import org.xwiki.rendering.block.match.MetadataBlockMatcher;
import org.xwiki.rendering.listener.MetaData;
import org.xwiki.rendering.macro.AbstractMacro;
import org.xwiki.rendering.macro.Macro;
import org.xwiki.rendering.macro.MacroContentParser;
import org.xwiki.rendering.macro.descriptor.ContentDescriptor;
import org.xwiki.rendering.transformation.MacroTransformationContext;
import org.xwiki.rendering.transformation.RenderingContext;

/**
* Base class to implement a macro which have content to execute.
*
* @param <P> the type of the macro parameters bean
* @version $Id$
* @since 14.8RC1
* @since 14.4.5
* @since 13.10.10
*/
public abstract class AbstractExecutedContentMacro<P> extends AbstractMacro<P>
{
@Inject
protected BlockAsyncRendererExecutor executor;

@Inject
protected MacroContentParser parser;

@Inject
protected DocumentAccessBridge documentAccessBridge;

@Inject
protected DocumentReferenceResolver<String> resolver;

@Inject
protected RenderingContext renderingContext;

/**
* Creates a new {@link Macro} instance.
*
* @param name the name of the macro (eg "Table Of Contents" for the TOC macro)
* @param description string describing this macro.
* @param contentDescriptor the {@link ContentDescriptor} describing the content of this macro.
* @param parametersBeanClass class of the parameters bean.
*/
protected AbstractExecutedContentMacro(String name, String description, ContentDescriptor contentDescriptor,
Class<?> parametersBeanClass)
{
super(name, description, contentDescriptor, parametersBeanClass);
}

@Override
public boolean supportsInlineMode()
{
return true;
}

protected String getCurrentSource(MacroTransformationContext context)
{
String currentSource = null;

if (context != null) {
currentSource =
context.getTransformationContext() != null ? context.getTransformationContext().getId() : null;

MacroBlock currentMacroBlock = context.getCurrentMacroBlock();

if (currentMacroBlock != null) {
MetaDataBlock metaDataBlock =
currentMacroBlock.getFirstBlock(new MetadataBlockMatcher(MetaData.SOURCE), Axes.ANCESTOR_OR_SELF);

if (metaDataBlock != null) {
currentSource = (String) metaDataBlock.getMetaData().getMetaData(MetaData.SOURCE);
}
}
}

return currentSource;
}

protected BlockAsyncRendererConfiguration createBlockAsyncRendererConfiguration(List<?> idElements, Block content,
MacroTransformationContext context)
{
return createBlockAsyncRendererConfiguration(idElements, content, getCurrentSource(context), context);
}

protected BlockAsyncRendererConfiguration createBlockAsyncRendererConfiguration(List<?> idElements, Block content,
String source, MacroTransformationContext context)
{
BlockAsyncRendererConfiguration configuration = new BlockAsyncRendererConfiguration(idElements, content);

// Set author
if (source != null) {
DocumentReference sourceReference = this.resolver.resolve(source);
configuration.setSecureReference(sourceReference, this.documentAccessBridge.getCurrentAuthorReference());

// Invalidate the cache when the document containing the macro call is modified
configuration.useEntity(sourceReference);
}

// Indicate if the result should be inline or not
configuration.setInline(context.isInline());

// Indicate the syntax of the content
configuration.setDefaultSyntax(this.parser.getCurrentSyntax(context));

// Indicate the target syntax
configuration.setTargetSyntax(this.renderingContext.getTargetSyntax());

// Set the transformation id
configuration.setTransformationId(context.getTransformationContext().getId());

return configuration;
}
}

0 comments on commit bd34ad6

Please sign in to comment.