Skip to content

Commit

Permalink
XWIKI-21730: Delete own comments should not require edit rights on page
Browse files Browse the repository at this point in the history
* Fixed codestyle
* Added a test for the new action
  • Loading branch information
Sereza7 committed Dec 23, 2024
1 parent 3201e8b commit 1579ded
Show file tree
Hide file tree
Showing 2 changed files with 181 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import java.io.IOException;

import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import javax.script.ScriptContext;
Expand All @@ -38,9 +39,13 @@
import com.xpn.xwiki.doc.XWikiDocument;
import com.xpn.xwiki.objects.BaseObject;

import org.xwiki.user.CurrentUserReference;
import org.xwiki.user.UserReference;
import org.xwiki.user.UserReferenceResolver;

/**
* Action used to remove a comment from a page, requires comment right but not edit right.
* Note that this class is largely inspired by ObjectRemoveAction and Comment
* Action used to remove a comment from a page, requires comment right but not edit right. Note that this class is
* largely inspired by ObjectRemoveAction and Comment
*
* @version $Id$
* @since 17.0.0RC1
Expand All @@ -51,8 +56,12 @@
public class CommentDeleteAction extends XWikiAction
{
private static final String FAIL_MESSAGE = "failed";

private static final Logger LOGGER = LoggerFactory.getLogger(CommentDeleteAction.class);

@Inject
private UserReferenceResolver<CurrentUserReference> currentUserResolver;

@Override
protected Class<? extends XWikiForm> getFormClass()
{
Expand All @@ -69,21 +78,23 @@ protected BaseObject getObject(XWikiDocument doc, XWikiContext context)
String attributeName = "message";
if (StringUtils.isBlank(className)) {
getCurrentScriptContext().setAttribute(attributeName,
localizePlainOrReturnKey("platform.core.action.commentRemove.noClassnameSpecified"),
ScriptContext.ENGINE_SCOPE);
localizePlainOrReturnKey("platform.core.action.commentRemove.noClassnameSpecified"),
ScriptContext.ENGINE_SCOPE);
} else if (classId < 0) {
getCurrentScriptContext().setAttribute(attributeName,
localizePlainOrReturnKey("platform.core.action.commentRemove.noCommentSpecified"),
ScriptContext.ENGINE_SCOPE);
localizePlainOrReturnKey("platform.core.action.commentRemove.noCommentSpecified"),
ScriptContext.ENGINE_SCOPE);
} else {
obj = doc.getObject(className, classId);
// Comment class reference
DocumentReference commentClass = new DocumentReference(context.getWikiId(), XWiki.SYSTEM_SPACE,
XWikiDocument.COMMENTSCLASS_REFERENCE.getName());
obj = doc.getXObject(commentClass, classId);
if (obj == null) {
getCurrentScriptContext().setAttribute(attributeName,
localizePlainOrReturnKey("platform.core.action.commentRemove.invalidComment"),
ScriptContext.ENGINE_SCOPE);
localizePlainOrReturnKey("platform.core.action.commentRemove.invalidComment"),
ScriptContext.ENGINE_SCOPE);
}
}

return obj;
}

Expand All @@ -110,8 +121,9 @@ public boolean action(XWikiContext context) throws XWikiException
return true;
}

doc.removeObject(obj);
doc.setAuthorReference(userReference);
doc.removeXObject(obj);
UserReference currentUserReference = this.currentUserResolver.resolve(CurrentUserReference.INSTANCE);
doc.getAuthors().setEffectiveMetadataAuthor(currentUserReference);

String changeComment = localizePlainOrReturnKey("core.comment.deleteComment");

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/*
* 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 com.xpn.xwiki.web;

import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.doc.XWikiDocument;
import com.xpn.xwiki.internal.store.StoreConfiguration;
import com.xpn.xwiki.objects.BaseObject;
import com.xpn.xwiki.test.MockitoOldcore;
import com.xpn.xwiki.test.junit5.mockito.InjectMockitoOldcore;
import com.xpn.xwiki.test.junit5.mockito.OldcoreTest;
import com.xpn.xwiki.test.reference.ReferenceComponentList;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.xwiki.csrf.CSRFToken;
import org.xwiki.localization.ContextualLocalizationManager;
import org.xwiki.model.document.DocumentAuthors;
import org.xwiki.model.reference.DocumentReference;
import org.xwiki.test.annotation.ComponentList;
import org.xwiki.test.junit5.mockito.InjectMockComponents;
import org.xwiki.test.junit5.mockito.MockComponent;
import org.xwiki.user.CurrentUserReference;
import org.xwiki.user.UserReference;
import org.xwiki.user.UserReferenceResolver;

import java.util.Locale;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

/**
* Unit tests for {@link com.xpn.xwiki.web.CommentDeleteAction}.
*
* @version $Id$
* @since 17.0.0RC1
*/
@ComponentList
@ReferenceComponentList
@OldcoreTest(mockXWiki = false)
class CommentDeleteActionTest
{
/**
* The object being tested.
*/
@InjectMockComponents
private final CommentDeleteAction commentDeleteAction = new CommentDeleteAction();

@InjectMockitoOldcore
private MockitoOldcore oldcore;

@MockComponent
private ContextualLocalizationManager localizationManager;

@MockComponent
private CSRFToken csrfToken;

@MockComponent
private UserReferenceResolver<CurrentUserReference> currentUserResolver;

@MockComponent
private StoreConfiguration storeConfiguration;

@Mock
private XWikiRequest request;

@Mock
private XWikiDocument mockDocument;

@Mock
private XWikiDocument mockClonedDocument;

@Mock
private XWikiDocument mockClonedTwiceDocument;

@Mock
private ObjectRemoveForm mockForm;

@Mock
private BaseObject mockComment;

@Mock
private DocumentAuthors mockAuthors;

@Mock
private UserReference currentUserReference;

XWikiContext context;

@BeforeEach
void setup()
{

this.context = this.oldcore.getXWikiContext();
this.context.setDoc(this.mockDocument);

when(this.mockDocument.clone()).thenReturn(this.mockClonedDocument);
when(this.mockClonedDocument.clone()).thenReturn(this.mockClonedTwiceDocument);
when(this.mockClonedDocument.getOriginalDocument()).thenReturn(this.mockDocument);

this.context.setForm(this.mockForm);
when(this.mockForm.getClassName()).thenReturn("XWikiComments");
when(this.mockForm.getClassId()).thenReturn(0);

when(this.mockClonedDocument.getXObject(any(), eq(0))).thenReturn(this.mockComment);
when(this.mockClonedDocument.getAuthors()).thenReturn(mockAuthors);
// Those are necessary for the call to checkSavingDocument made while deleting the comment.
DocumentReference documentReference = new DocumentReference("XWiki", "Foo", "Bar",
Locale.ENGLISH);
when(mockClonedDocument.getDocumentReference()).thenReturn(documentReference);
when(mockClonedDocument.getDocumentReferenceWithLocale()).thenReturn(documentReference);

when(this.currentUserResolver.resolve(CurrentUserReference.INSTANCE)).thenReturn(this.currentUserReference);
when(commentDeleteAction.localizePlainOrReturnKey("core.comment.deleteComment"))
.thenReturn("changeComment");

this.context.setRequest(this.request);
when(this.csrfToken.isTokenValid(null)).thenReturn(true);
}

/**
* Deletes a comment.
*/
@Test
void deleteComment() throws Exception
{
// First, we check that the request has returned the right result.
assertFalse(this.commentDeleteAction.action(this.context));
// Then, we check that we did take CSRF validation into consideration
verify(this.csrfToken).isTokenValid(null);
// Then, we make sure that the comment provided was actually removed
verify(this.mockClonedDocument).removeXObject(this.mockComment);
// And that the document where it stood was saved.
verify(context.getWiki()).saveDocument(mockClonedDocument, "changeComment", true, context);
}
}

0 comments on commit 1579ded

Please sign in to comment.