Skip to content

Commit bb7068b

Browse files
committed
XWIKI-17794: Properly interpret velocity in gadget titles
1 parent 5308f7d commit bb7068b

File tree

2 files changed

+79
-21
lines changed

2 files changed

+79
-21
lines changed

xwiki-platform-core/xwiki-platform-dashboard/xwiki-platform-dashboard-macro/src/main/java/org/xwiki/rendering/internal/macro/dashboard/DefaultGadgetSource.java

+28-10
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,16 @@
4444
import org.xwiki.rendering.block.WordBlock;
4545
import org.xwiki.rendering.block.XDOM;
4646
import org.xwiki.rendering.executor.ContentExecutor;
47-
import org.xwiki.rendering.executor.ContentExecutorException;
4847
import org.xwiki.rendering.listener.reference.ResourceReference;
4948
import org.xwiki.rendering.listener.reference.ResourceType;
5049
import org.xwiki.rendering.macro.dashboard.Gadget;
5150
import org.xwiki.rendering.macro.dashboard.GadgetSource;
52-
import org.xwiki.rendering.parser.MissingParserException;
53-
import org.xwiki.rendering.parser.ParseException;
5451
import org.xwiki.rendering.syntax.Syntax;
5552
import org.xwiki.rendering.transformation.MacroTransformationContext;
5653
import org.xwiki.rendering.util.ParserUtils;
5754
import org.xwiki.security.authorization.AuthorExecutor;
55+
import org.xwiki.security.authorization.AuthorizationManager;
56+
import org.xwiki.security.authorization.Right;
5857
import org.xwiki.velocity.VelocityEngine;
5958
import org.xwiki.velocity.VelocityManager;
6059

@@ -120,6 +119,9 @@ public class DefaultGadgetSource implements GadgetSource
120119
@Inject
121120
private JobProgressManager progress;
122121

122+
@Inject
123+
private AuthorizationManager authorizationManager;
124+
123125
/**
124126
* Prepare the parser to parse the title and content of the gadget into blocks.
125127
*/
@@ -194,19 +196,23 @@ private List<Gadget> prepareGadgets(List<BaseObject> objects, Syntax sourceSynta
194196
String position = xObject.getStringValue("position");
195197
String id = xObject.getNumber() + "";
196198

197-
// render title with velocity
198-
StringWriter writer = new StringWriter();
199-
// FIXME: the engine has an issue with $ and # as last character. To test and fix if it happens
200-
velocityEngine.evaluate(velocityContext, writer, key, title);
201-
String gadgetTitle = writer.toString();
199+
String gadgetTitle;
200+
201+
XWikiDocument ownerDocument = xObject.getOwnerDocument();
202+
if (this.authorizationManager.hasAccess(Right.SCRIPT, ownerDocument.getAuthorReference(), ownerDocument.getDocumentReference())) {
203+
gadgetTitle =
204+
this.evaluateVelocityTitle(velocityContext, velocityEngine, key, title, ownerDocument);
205+
} else {
206+
gadgetTitle = title;
207+
}
202208

203209
// parse both the title and content in the syntax of the transformation context
204210
List<Block> titleBlocks =
205211
renderGadgetProperty(gadgetTitle, sourceSyntax, xObject.getDocumentReference(),
206-
xObject.getOwnerDocument(), context);
212+
ownerDocument, context);
207213
List<Block> contentBlocks =
208214
renderGadgetProperty(content, sourceSyntax, xObject.getDocumentReference(),
209-
xObject.getOwnerDocument(), context);
215+
ownerDocument, context);
210216

211217
// create a gadget will all these and add the gadget to the container of gadgets
212218
Gadget gadget = new Gadget(id, titleBlocks, contentBlocks, position);
@@ -222,6 +228,18 @@ private List<Gadget> prepareGadgets(List<BaseObject> objects, Syntax sourceSynta
222228
return gadgets;
223229
}
224230

231+
private String evaluateVelocityTitle(VelocityContext velocityContext, VelocityEngine velocityEngine, String key,
232+
String title, XWikiDocument ownerDocument) throws Exception
233+
{
234+
return this.authorExecutor.call(() -> {
235+
// render title with velocity
236+
StringWriter writer = new StringWriter();
237+
// FIXME: the engine has an issue with $ and # as last character. To test and fix if it happens
238+
velocityEngine.evaluate(velocityContext, writer, key, title);
239+
return writer.toString();
240+
}, ownerDocument.getAuthorReference(), ownerDocument.getDocumentReference());
241+
}
242+
225243
private List<Block> renderGadgetProperty(String content, Syntax sourceSyntax, EntityReference sourceReference,
226244
XWikiDocument ownerDocument, MacroTransformationContext context)
227245
throws Exception

xwiki-platform-core/xwiki-platform-dashboard/xwiki-platform-dashboard-macro/src/test/java/org/xwiki/rendering/internal/macro/dashboard/DefaultGadgetSourceTest.java

+51-11
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
import org.xwiki.rendering.transformation.MacroTransformationContext;
4242
import org.xwiki.rendering.transformation.TransformationContext;
4343
import org.xwiki.security.authorization.AuthorExecutor;
44+
import org.xwiki.security.authorization.AuthorizationManager;
45+
import org.xwiki.security.authorization.Right;
4446
import org.xwiki.test.junit5.mockito.ComponentTest;
4547
import org.xwiki.test.junit5.mockito.InjectMockComponents;
4648
import org.xwiki.test.junit5.mockito.MockComponent;
@@ -57,6 +59,7 @@
5759
import static org.mockito.ArgumentMatchers.any;
5860
import static org.mockito.ArgumentMatchers.eq;
5961
import static org.mockito.Mockito.mock;
62+
import static org.mockito.Mockito.verify;
6063
import static org.mockito.Mockito.when;
6164

6265
@ComponentTest
@@ -72,6 +75,9 @@ class DefaultGadgetSourceTest
7275
@MockComponent
7376
private AuthorExecutor authorExecutor;
7477

78+
@MockComponent
79+
private AuthorizationManager authorizationManager;
80+
7581
@Mock
7682
private DocumentReference documentReference;
7783

@@ -99,6 +105,11 @@ class DefaultGadgetSourceTest
99105
@Mock
100106
private MacroTransformationContext macroTransformationContext;
101107

108+
@Mock
109+
private VelocityEngine velocityEngine;
110+
111+
private ContentExecutor<MacroTransformationContext> contentExecutor;
112+
102113
@BeforeEach
103114
void setup(MockitoComponentManager componentManager) throws Exception
104115
{
@@ -123,23 +134,14 @@ void setup(MockitoComponentManager componentManager) throws Exception
123134
when(transformationContext.getId()).thenReturn(transformationId);
124135

125136
VelocityManager velocityManager = componentManager.getInstance(VelocityManager.class);
126-
VelocityEngine velocityEngine = mock(VelocityEngine.class);
127137
when(velocityManager.getVelocityEngine()).thenReturn(velocityEngine);
128-
when(velocityEngine.evaluate(any(), any(), any(), any(String.class))).then((Answer<Void>) invocation -> {
129-
Object[] args = invocation.getArguments();
130-
StringWriter stringWriter = (StringWriter) args[1];
131-
String title = (String) args[3];
132-
stringWriter.append(title);
133-
return null;
134-
});
135138

136-
AuthorExecutor authorExecutor = componentManager.getInstance(AuthorExecutor.class);
137139
when(authorExecutor.call(any(), eq(ownerAuthorReference), eq(ownerSourceReference))).then(invocationOnMock -> {
138140
Callable callable = (Callable) invocationOnMock.getArguments()[0];
139141
return callable.call();
140142
});
141143

142-
ContentExecutor<MacroTransformationContext> contentExecutor =
144+
this.contentExecutor =
143145
componentManager.getInstance(ContentExecutor.TYPE_MACRO_TRANSFORMATION);
144146
when(contentExecutor.execute(any(), any(), any(), any())).then((Answer<XDOM>) invocationOnMock -> {
145147
String content = invocationOnMock.getArgument(0);
@@ -162,12 +164,50 @@ void getGadgets() throws Exception
162164
when(gadgetObject1.getLargeStringValue("content")).thenReturn("Some content");
163165
when(gadgetObject1.getStringValue("position")).thenReturn("0");
164166
when(gadgetObject1.getNumber()).thenReturn(42);
167+
when(this.authorizationManager.hasAccess(Right.SCRIPT, ownerAuthorReference, ownerSourceReference)).thenReturn(true);
168+
when(this.velocityEngine.evaluate(any(), any(), any(), eq("Gadget 1"))).then((Answer<Void>) invocation -> {
169+
Object[] args = invocation.getArguments();
170+
StringWriter stringWriter = (StringWriter) args[1];
171+
String title = "Evaluated velocity version of gadget 1";
172+
stringWriter.append(title);
173+
return null;
174+
});
165175

166176
List<Gadget> gadgets = this.defaultGadgetSource.getGadgets(testSource, macroTransformationContext);
167177
assertEquals(1, gadgets.size());
168178
Gadget gadget = gadgets.get(0);
169-
assertEquals("Gadget 1", gadget.getTitle().get(0).toString());
179+
assertEquals("Evaluated velocity version of gadget 1", gadget.getTitle().get(0).toString());
170180
assertEquals("Some content", gadget.getContent().get(0).toString());
171181
assertEquals("42", gadget.getId());
182+
verify(this.contentExecutor)
183+
.execute(eq("Evaluated velocity version of gadget 1"), any(), any(), any());
184+
verify(this.contentExecutor)
185+
.execute(eq("Some content"), any(), any(), any());
186+
}
187+
188+
@Test
189+
void getGadgetWithoutScriptRight() throws Exception
190+
{
191+
assertEquals(new ArrayList<>(), this.defaultGadgetSource.getGadgets(testSource, macroTransformationContext));
192+
193+
BaseObject gadgetObject1 = mock(BaseObject.class);
194+
when(xWikiDocument.getXObjects(gadgetClassReference)).thenReturn(Collections.singletonList(gadgetObject1));
195+
when(gadgetObject1.getOwnerDocument()).thenReturn(ownerDocument);
196+
when(gadgetObject1.getStringValue("title")).thenReturn("Gadget 2");
197+
when(gadgetObject1.getLargeStringValue("content")).thenReturn("Some other content");
198+
when(gadgetObject1.getStringValue("position")).thenReturn("2");
199+
when(gadgetObject1.getNumber()).thenReturn(12);
200+
when(this.authorizationManager.hasAccess(Right.SCRIPT, ownerAuthorReference, ownerSourceReference)).thenReturn(false);
201+
202+
List<Gadget> gadgets = this.defaultGadgetSource.getGadgets(testSource, macroTransformationContext);
203+
assertEquals(1, gadgets.size());
204+
Gadget gadget = gadgets.get(0);
205+
assertEquals("Gadget 2", gadget.getTitle().get(0).toString());
206+
assertEquals("Some other content", gadget.getContent().get(0).toString());
207+
assertEquals("12", gadget.getId());
208+
verify(this.contentExecutor)
209+
.execute(eq("Gadget 2"), any(), any(), any());
210+
verify(this.contentExecutor)
211+
.execute(eq("Some other content"), any(), any(), any());
172212
}
173213
}

0 commit comments

Comments
 (0)