Skip to content

Commit

Permalink
XWIKI-21257: Rollback is not triggering a UserUpdatingDocumentEvent
Browse files Browse the repository at this point in the history
  * Ensure that the rollback API properly calls the check method
  * Back the changes in a unit test that check events triggered in
    rollback

(cherry picked from commit 4de7287)
  • Loading branch information
surli committed Sep 5, 2023
1 parent 85a06cb commit 4fa7f30
Show file tree
Hide file tree
Showing 8 changed files with 488 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* 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.test;

import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.xwiki.component.annotation.Component;
import org.xwiki.model.reference.DocumentReference;
import org.xwiki.observation.AbstractEventListener;
import org.xwiki.observation.event.Event;

import com.xpn.xwiki.doc.XWikiDocument;
import com.xpn.xwiki.internal.event.UserUpdatingDocumentEvent;

/**
* Listener dedicated to cancel a specific rolling back event triggered in VersionIT test.
*
* @version $Id$
* @since 14.10.17
* @since 15.5.3
* @since 15.8RC1
*/
@Component
@Singleton
@Named(CustomUserUpdatedDocumentEventListener.NAME)
public class CustomUserUpdatedDocumentEventListener extends AbstractEventListener
{
static final String NAME = "CustomUserUpdatedDocumentEventListener";

@Inject
private Logger logger;

/**
* Default constructor.
*/
public CustomUserUpdatedDocumentEventListener()
{
super(NAME, new UserUpdatingDocumentEvent());
}

@Override
public void onEvent(Event event, Object source, Object data)
{
UserUpdatingDocumentEvent userEvent = (UserUpdatingDocumentEvent) event;
XWikiDocument sourceDoc = (XWikiDocument) source;
DocumentReference expectedReference = new DocumentReference("xwiki", "XWiki", "XWikiPreferences");
if (StringUtils.equals(userEvent.getUserReference().getName(), "DeleteVersionTestUserCancelEvent")
&& sourceDoc.getDocumentReference().equals(expectedReference)) {
logger.info("Cancelling user event on purpose");
userEvent.cancel();
}
}
}
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
org.xwiki.test.CustomUserUpdatedDocumentEventListener
org.xwiki.test.TestMacro

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -4704,6 +4704,27 @@ public void checkDeletingDocument(DocumentReference userReference, XWikiDocument
@Unstable
public void deleteDocumentVersions(XWikiDocument document, String version1, String version2, XWikiContext context)
throws XWikiException
{
deleteDocumentVersions(document, version1, version2, false, context);
}

/**
* Delete a range of versions from a document history.
*
* @param document the document from which to delete versions
* @param version1 one end of the versions range to remove
* @param version2 the other end of the versions range to remove
* @param triggeredByUser {@code true} if the API is called directly by an action from a user and checks need to
* be performed for the rollback (See: {@link #rollback(XWikiDocument, String, boolean, boolean, XWikiContext)}).
* @param context the XWiki context
* @throws XWikiException
* @since 14.10.17
* @since 15.5.3
* @since 15.8RC1
*/
@Unstable
public void deleteDocumentVersions(XWikiDocument document, String version1, String version2,
boolean triggeredByUser, XWikiContext context) throws XWikiException
{
Version v1 = new Version(version1);
Version v2 = new Version(version2);
Expand Down Expand Up @@ -4746,20 +4767,22 @@ public void deleteDocumentVersions(XWikiDocument document, String version1, Stri
.notify(new DocumentVersionRangeDeletingEvent(document.getDocumentReferenceWithLocale(),
lowerBound.toString(), upperBound.toString()), document, context);

// Update the archive
context.getWiki().getVersioningStore().saveXWikiDocArchive(archive, true, context);
// Make sure the cached document archive is updated too
XWikiDocument cachedDocument =
context.getWiki().getDocument(document.getDocumentReferenceWithLocale(), context);
cachedDocument.setDocumentArchive(archive);

// There are still some versions left.
// If we delete the most recent (current) version, then rollback to latest undeleted version.
// We do that right before updating the archive, in case it would cancel the action.
Version previousVersion = archive.getLatestVersion();
if (!document.getRCSVersion().equals(previousVersion)) {
context.getWiki().rollback(document, previousVersion.toString(), false, context);
context.getWiki().rollback(document, previousVersion.toString(), false, triggeredByUser, context);
}

// Update the archive
context.getWiki().getVersioningStore().saveXWikiDocArchive(archive, true, context);
// Make sure the cached document archive is updated too
XWikiDocument cachedDocument =
context.getWiki().getDocument(document.getDocumentReferenceWithLocale(), context);
cachedDocument.setDocumentArchive(archive);

// Notify after versions delete
getObservationManager()
.notify(new DocumentVersionRangeDeletedEvent(document.getDocumentReferenceWithLocale(),
Expand Down Expand Up @@ -7602,6 +7625,25 @@ private void restoreDeletedAttachment(XWikiAttachment rolledbackAttachment, XWik
*/
public XWikiDocument rollback(final XWikiDocument tdoc, String rev, boolean addRevision, XWikiContext xcontext)
throws XWikiException
{
return rollback(tdoc, rev, addRevision, false, xcontext);
}

/**
* @param tdoc the document to rollback
* @param rev the revision to rollback to
* @param addRevision true if a new revision should be created
* @param triggeredByUser {@code true} if this has been triggered by a user and a check needs to be performed
* @param xcontext the XWiki context
* @return the new document
* @throws XWikiException when failing to rollback the document
* @since 14.10.17
* @since 15.5.3
* @since 15.8RC1
*/
@Unstable
public XWikiDocument rollback(final XWikiDocument tdoc, String rev, boolean addRevision,
boolean triggeredByUser, XWikiContext xcontext) throws XWikiException
{
LOGGER.debug("Rolling back [{}] to version [{}]", tdoc, rev);

Expand Down Expand Up @@ -7680,6 +7722,10 @@ public XWikiDocument rollback(final XWikiDocument tdoc, String rev, boolean addR
message = localizePlainOrKey("core.comment.rollback", rev);
}

if (triggeredByUser) {
checkSavingDocument(xcontext.getUserReference(), document, message, false, xcontext);
}

ObservationManager om = getObservationManager();
if (om != null) {
// Notify listeners about the document that is going to be rolled back.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public boolean action(XWikiContext context) throws XWikiException
Version v2 = versions[1];

if (v1 != null && v2 != null) {
context.getWiki().deleteDocumentVersions(tdoc, v1.toString(), v2.toString(), context);
context.getWiki().deleteDocumentVersions(tdoc, v1.toString(), v2.toString(), true, context);
}

sendRedirect(context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public boolean action(XWikiContext context) throws XWikiException
}

// Perform the rollback.
xwiki.rollback(tdoc, rev, context);
xwiki.rollback(tdoc, rev, true, true, context);

// Forward to view.
String redirect = Utils.getRedirect("view", context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
import com.xpn.xwiki.doc.XWikiDocument;
import com.xpn.xwiki.internal.ReadOnlyXWikiContextProvider;
import com.xpn.xwiki.internal.debug.DebugConfiguration;
import com.xpn.xwiki.internal.event.UserUpdatingDocumentEvent;
import com.xpn.xwiki.internal.render.groovy.ParseGroovyFromString;
import com.xpn.xwiki.internal.skin.InternalSkinManager;
import com.xpn.xwiki.internal.store.StoreConfiguration;
Expand Down Expand Up @@ -216,7 +217,7 @@ public void copyDocumentPreservesAttachmentsVersion() throws Exception
}

/**
* Verify that {@link XWiki#rollback(XWikiDocument, String, XWikiContext)} fires the right events.
* Verify that {@link XWiki#rollback(XWikiDocument, String, boolean, boolean, XWikiContext)} fires the right events.
*/
@Test
public void rollbackFiresEvents() throws Exception
Expand All @@ -236,17 +237,22 @@ public void rollbackFiresEvents() throws Exception
XWikiDocument result = mock(XWikiDocument.class);
when(result.getDocumentReference()).thenReturn(documentReference);

DocumentReference userReference = new DocumentReference("xwiki", "XWiki", "ContextUser");
this.context.setUserReference(userReference);

String revision = "3.5";
when(this.documentRevisionProvider.getRevision(document, revision)).thenReturn(result);

this.componentManager.registerMockComponent(ContextualLocalizationManager.class);

xwiki.rollback(document, revision, context);
xwiki.rollback(document, revision, true, true, context);

verify(observationManager).notify(new DocumentRollingBackEvent(documentReference, revision), document, context);
verify(observationManager).notify(new DocumentUpdatingEvent(documentReference), document, context);
verify(observationManager).notify(new DocumentUpdatedEvent(documentReference), document, context);
verify(observationManager).notify(new DocumentRolledBackEvent(documentReference, revision), document, context);
verify(observationManager).notify(new UserUpdatingDocumentEvent(userReference, documentReference),
document, context);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,4 +183,30 @@ public ComparePage compare(String fromVersion, String toVersion)
getDriver().findElementWithoutWaiting(pane, By.xpath(".//input[@accesskey = 'c']")).click();
return new ComparePage();
}

/**
* @return the total number of versions contained in the history as returned by the live table
* @since 14.10.17
* @since 15.5.3
* @since 15.8RC1
*/
public int getNumberOfVersions()
{
String xpath = ".//div[@class='paginationFilter' and following-sibling::div[@id='historycontent']]";
WebElement paginationDiv = getDriver().findElementWithoutWaiting(By.xpath(xpath));
return Integer.parseInt(getDriver().findElementWithoutWaiting(paginationDiv, By.className("totalResultsNo"))
.getText());
}

/**
* @return {@code true} if the requested version is currently displayed in the history
* @since 14.10.17
* @since 15.5.3
* @since 15.8RC1
*/
public boolean hasVersion(String version)
{
String xpath = String.format(".//table//tr[contains(., '%s')]", version);
return getDriver().hasElementWithoutWaiting(pane, By.xpath(xpath));
}
}

0 comments on commit 4fa7f30

Please sign in to comment.