Skip to content

Commit

Permalink
XWIKI-22726: Allow customizing the validation of HQL queries through …
Browse files Browse the repository at this point in the history
…configuration

* add unit tests
  • Loading branch information
tmortagne committed Dec 13, 2024
1 parent b4c568b commit 8d53032
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,19 @@ private List<Pattern> getPatterns(String key)
{
List<String> patternStrings = this.configuration.getProperty(key, List.class);

List<Pattern> patterns = new ArrayList<>(patternStrings.size());
for (String patternString : patternStrings) {
try {
patterns.add(Pattern.compile(patternString));
} catch (Exception e) {
this.logger.warn("Failed to parse pattern [{}] for configuration [{}]: {}", patternString, key,
ExceptionUtils.getRootCauseMessage(e));
List<Pattern> patterns;
if (patternStrings != null) {
patterns = new ArrayList<>(patternStrings.size());
for (String patternString : patternStrings) {
try {
patterns.add(Pattern.compile(patternString));
} catch (Exception e) {
this.logger.warn("Failed to parse pattern [{}] for configuration [{}]: {}", patternString, key,
ExceptionUtils.getRootCauseMessage(e));
}
}
} else {
patterns = List.of();
}

return patterns;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,16 @@
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.xwiki.component.manager.ComponentManager;
import org.xwiki.configuration.ConfigurationSource;
import org.xwiki.context.Execution;
import org.xwiki.context.ExecutionContext;
import org.xwiki.query.Query;
import org.xwiki.query.QueryException;
import org.xwiki.query.QueryFilter;
import org.xwiki.query.WrappingQuery;
import org.xwiki.query.hql.internal.ConfigurableHQLCompleteStatementValidator;
import org.xwiki.query.hql.internal.DefaultHQLStatementValidator;
import org.xwiki.query.hql.internal.HQLCompleteStatementValidator;
import org.xwiki.query.hql.internal.StandardHQLCompleteStatementValidator;
import org.xwiki.query.internal.DefaultQuery;
import org.xwiki.security.authorization.ContextualAuthorizationManager;
Expand Down Expand Up @@ -77,14 +80,18 @@
* @version $Id$
*/
@ComponentTest
@ComponentList({DefaultHQLStatementValidator.class, StandardHQLCompleteStatementValidator.class})
@ComponentList({DefaultHQLStatementValidator.class, StandardHQLCompleteStatementValidator.class,
ConfigurableHQLCompleteStatementValidator.class})
class HqlQueryExecutorTest
{
@InjectMockComponents
private HqlQueryExecutor executor;

@InjectMockComponents
private DefaultHQLStatementValidator defaultQueryValidator;
private DefaultHQLStatementValidator defaultValidator;

@InjectMockComponents
private ConfigurableHQLCompleteStatementValidator configurableValidator;

@MockComponent
private ContextualAuthorizationManager authorization;
Expand All @@ -98,6 +105,10 @@ class HqlQueryExecutorTest
@MockComponent
private Execution execution;

@MockComponent
@Named("xwikiproperties")
private ConfigurationSource xwikiproperties;

@MockComponent
@Named("context")
private ComponentManager contextComponentMannager;
Expand All @@ -109,6 +120,11 @@ public void afterComponent()
{
when(this.hibernateStore.getConfiguration()).thenReturn(new Configuration());
when(this.hibernateStore.getConfigurationMetadata()).thenReturn(mock(Metadata.class));

when(this.xwikiproperties.getProperty("query.hql.safe", List.class))
.thenReturn(List.of("select normallynotallowed from XWikiDocument as doc where 1=\\d+"));
when(this.xwikiproperties.getProperty("query.hql.unsafe", List.class))
.thenReturn(List.of("select name from XWikiDocument as doc where 1=\\d+"));
}

@BeforeEach
Expand All @@ -125,6 +141,10 @@ public Boolean answer(InvocationOnMock invocation) throws Throwable

this.hasProgrammingRight = true;

when(this.contextComponentMannager
.<HQLCompleteStatementValidator>getInstanceList(HQLCompleteStatementValidator.class))
.thenReturn(List.of(configurableValidator));

// Actual Hibernate query

ExecutionContext executionContext = mock(ExecutionContext.class);
Expand Down Expand Up @@ -383,7 +403,6 @@ void executeShortFromHQLQueryWithProgrammingRights() throws QueryException
void executeCompleteHQLQueryWithProgrammingRights() throws QueryException
{
execute("select u from XWikiDocument as doc", true);

}

@Test
Expand All @@ -404,6 +423,12 @@ void executeShortFromHQLQueryWithoutProgrammingRights() throws QueryException
execute(", BaseObject as obj", false);
}

@Test
void executeWhenOverwrittenAllowedSelect() throws Exception
{
execute("select normallynotallowed from XWikiDocument as doc where 1=42", false);
}

// Not allowed

@Test
Expand Down Expand Up @@ -456,4 +481,17 @@ void executeUpdateWithoutProgrammingRight() throws Exception
expected.getCause().getMessage());
}
}

@Test
void executeWhenOverwrittenUnsafeSelect() throws Exception
{
try {
execute("select name from XWikiDocument as doc where 1=42", false);
} catch (QueryException expected) {
assertEquals(
"The query requires programming right."
+ " Query statement = [select name from XWikiDocument as doc where 1=42]",
expected.getCause().getMessage());
}
}
}

0 comments on commit 8d53032

Please sign in to comment.