Skip to content
Permalink
Browse files Browse the repository at this point in the history
XWIKI-9119: Refactoring of SkinExtensionPlugin
  * Provide some tests
  • Loading branch information
surli committed Oct 12, 2022
1 parent 4fac9f2 commit fe65bc3
Show file tree
Hide file tree
Showing 5 changed files with 553 additions and 37 deletions.
Expand Up @@ -31,7 +31,7 @@
<name>XWiki Platform - Skin - Skin Extensions</name>
<description>XWiki Platform - Skin - Skin Extensions</description>
<properties>
<xwiki.jacoco.instructionRatio>0.18</xwiki.jacoco.instructionRatio>
<xwiki.jacoco.instructionRatio>0.25</xwiki.jacoco.instructionRatio>
</properties>
<dependencies>
<!-- Build tools -->
Expand Down
Expand Up @@ -29,6 +29,7 @@
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xwiki.bridge.event.DocumentCreatedEvent;
Expand All @@ -37,6 +38,7 @@
import org.xwiki.bridge.event.WikiDeletedEvent;
import org.xwiki.model.EntityType;
import org.xwiki.model.reference.DocumentReference;
import org.xwiki.model.reference.DocumentReferenceResolver;
import org.xwiki.model.reference.EntityReferenceResolver;
import org.xwiki.model.reference.EntityReferenceSerializer;
import org.xwiki.observation.EventListener;
Expand Down Expand Up @@ -85,6 +87,10 @@ public abstract class AbstractDocumentSkinExtensionPlugin extends AbstractSkinEx
*/
private final List<Event> events = new ArrayList<>(3);

private AuthorizationManager authorizationManager;
private DocumentReferenceResolver<String> stringDocumentReferenceResolver;
private EntityReferenceResolver<String> currentEntityReferenceResolver;

/**
* XWiki plugin constructor.
*
Expand Down Expand Up @@ -174,7 +180,7 @@ public void virtualInit(XWikiContext context)
@Override
public Set<String> getAlwaysUsedExtensions(XWikiContext context)
{
EntityReferenceSerializer<String> serializer = Utils.getComponent(EntityReferenceSerializer.TYPE_STRING);
EntityReferenceSerializer<String> serializer = getDefaultEntityReferenceSerializer();
Set<DocumentReference> references = getAlwaysUsedExtensions();
Set<String> names = new HashSet<>(references.size());
for (DocumentReference reference : references) {
Expand Down Expand Up @@ -214,7 +220,7 @@ public Set<DocumentReference> getAlwaysUsedExtensions()
XWikiDocument doc = context.getWiki().getDocument(extension, context);
// Only add the extension as being "always used" if the page holding it has been saved with
// programming rights.
if (Utils.getComponent(AuthorizationManager.class).hasAccess(Right.PROGRAM,
if (getAuthorizationManager().hasAccess(Right.PROGRAM,
doc.getAuthorReference(), doc.getDocumentReference())) {
extensions.add(extension);
}
Expand All @@ -236,36 +242,83 @@ public Set<DocumentReference> getAlwaysUsedExtensions()
public boolean hasPageExtensions(XWikiContext context)
{
XWikiDocument doc = context.getDoc();
if (doc != null) {
List<BaseObject> objects = doc.getObjects(getExtensionClassName());
if (objects != null) {
for (BaseObject obj : objects) {
if (obj == null) {
continue;
}
if (obj.getStringValue(USE_FIELDNAME).equals("currentPage")) {
return true;
}
boolean result = false;
if (doc != null && this.hasCurrentPageExtensionObjects(doc)) {
if (getAuthorizationManager().hasAccess(Right.SCRIPT, doc.getAuthorReference(),
doc.getDocumentReference())) {
result = true;
} else {
displayScriptRightLog(doc.getDocumentReference());
}
}
return result;
}

private void displayScriptRightLog(Object documentReference)
{
LOGGER.warn("Extensions present in [{}] ignored because of lack of script right from the author.",
documentReference);
}

private boolean hasCurrentPageExtensionObjects(XWikiDocument doc)
{
List<BaseObject> objects = doc.getObjects(getExtensionClassName());
if (objects != null) {
for (BaseObject obj : objects) {
if (obj == null) {
continue;
}
if (StringUtils.equals(obj.getStringValue(USE_FIELDNAME), "currentPage")) {
return true;
}
}
}
return false;
}

@Override
public void use(String resource, XWikiContext context)
public void use(String resource, Map<String, Object> parameters, XWikiContext context)
{
String canonicalResource = getCanonicalDocumentName(resource);

super.use(canonicalResource, context);
if (this.canResourceBeUsed(canonicalResource, context)) {
super.use(canonicalResource, parameters, context);
} else {
displayScriptRightLog(canonicalResource);
}
}

@Override
public void use(String resource, Map<String, Object> parameters, XWikiContext context)
private DocumentReferenceResolver<String> getDocumentReferenceResolver()
{
String canonicalResource = getCanonicalDocumentName(resource);
if (this.stringDocumentReferenceResolver == null) {
this.stringDocumentReferenceResolver = Utils.getComponent(DocumentReferenceResolver.TYPE_STRING);
}
return this.stringDocumentReferenceResolver;
}

super.use(canonicalResource, parameters, context);
private AuthorizationManager getAuthorizationManager()
{
if (this.authorizationManager == null) {
this.authorizationManager = Utils.getComponent(AuthorizationManager.class);
}
return this.authorizationManager;
}

private boolean canResourceBeUsed(String resource, XWikiContext context)
{
DocumentReferenceResolver<String> documentReferenceResolver = getDocumentReferenceResolver();
DocumentReference documentReference = documentReferenceResolver.resolve(resource);

try {
XWikiDocument document = context.getWiki().getDocument(documentReference, context);
DocumentReference authorReference = document.getAuthorReference();
return getAuthorizationManager().hasAccess(Right.SCRIPT, authorReference, documentReference);
} catch (XWikiException e) {
LOGGER.error("Error while loading [{}] for checking script right: [{}]", documentReference,
ExceptionUtils.getRootCauseMessage(e));
LOGGER.debug("Original error stack trace: ", e);
return false;
}
}

/**
Expand Down Expand Up @@ -332,7 +385,7 @@ private void onDocumentEvent(XWikiDocument document)
if (document.getObject(getExtensionClassName()) != null) {
// new or already existing object
if (document.getObject(getExtensionClassName(), USE_FIELDNAME, "always", false) != null) {
if (Utils.getComponent(AuthorizationManager.class).hasAccess(Right.PROGRAM,
if (getAuthorizationManager().hasAccess(Right.PROGRAM,
document.getAuthorReference(), document.getDocumentReference())) {
getAlwaysUsedExtensions().add(document.getDocumentReference());

Expand All @@ -355,6 +408,14 @@ private void onDocumentEvent(XWikiDocument document)
}
}

private EntityReferenceResolver<String> getCurrentEntityReferenceResolver()
{
if (this.currentEntityReferenceResolver == null) {
this.currentEntityReferenceResolver = Utils.getComponent(EntityReferenceResolver.TYPE_STRING, "current");
}
return this.currentEntityReferenceResolver;
}

/**
* Get the canonical serialization of a document name, in the {@code wiki:Space.Document} format.
*
Expand All @@ -363,10 +424,8 @@ private void onDocumentEvent(XWikiDocument document)
*/
private String getCanonicalDocumentName(String documentName)
{
@SuppressWarnings("unchecked")
EntityReferenceResolver<String> resolver = Utils.getComponent(EntityReferenceResolver.TYPE_STRING, "current");
@SuppressWarnings("unchecked")
EntityReferenceSerializer<String> serializer = Utils.getComponent(EntityReferenceSerializer.TYPE_STRING);
EntityReferenceResolver<String> resolver = getCurrentEntityReferenceResolver();
EntityReferenceSerializer<String> serializer = getDefaultEntityReferenceSerializer();
return serializer.serialize(resolver.resolve(documentName, EntityType.DOCUMENT));
}

Expand Down
Expand Up @@ -229,14 +229,7 @@ private void useResource(String resource, XWikiContext context)
*/
public void use(String resource, XWikiContext context)
{
useResource(resource, context);

// In case a previous call added some parameters, remove them, since the last call for a resource always
// discards previous ones.
getParametersMap(context).remove(resource);

// Register the use of the resource in case the current execution is an asynchronous renderer
getSkinExtensionAsync().use(getName(), resource, null);
use(resource, null, context);
}

/**
Expand All @@ -256,8 +249,14 @@ public void use(String resource, Map<String, Object> parameters, XWikiContext co
{
useResource(resource, context);

// Associate parameters to the resource
getParametersMap(context).put(resource, parameters);
// In case a previous call added some parameters, remove them, since the last call for a resource always
// discards previous ones.
if (parameters == null) {
getParametersMap(context).remove(resource);
} else {
// Associate parameters to the resource
getParametersMap(context).put(resource, parameters);
}

getSkinExtensionAsync().use(getName(), resource, parameters);
}
Expand Down

0 comments on commit fe65bc3

Please sign in to comment.