/*
* 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.wiki.script;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import javax.inject.Provider;
import org.apache.commons.lang3.StringUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.xwiki.component.util.DefaultParameterizedType;
import org.xwiki.context.Execution;
import org.xwiki.context.ExecutionContext;
import org.xwiki.model.reference.DocumentReference;
import org.xwiki.model.reference.EntityReferenceSerializer;
import org.xwiki.model.reference.WikiReference;
import org.xwiki.script.service.ScriptServiceManager;
import org.xwiki.security.authorization.AccessDeniedException;
import org.xwiki.security.authorization.AuthorizationManager;
import org.xwiki.security.authorization.Right;
import org.xwiki.test.mockito.MockitoComponentMockingRule;
import org.xwiki.url.internal.standard.StandardURLConfiguration;
import org.xwiki.wiki.configuration.WikiConfiguration;
import org.xwiki.wiki.descriptor.WikiDescriptor;
import org.xwiki.wiki.descriptor.WikiDescriptorManager;
import org.xwiki.wiki.internal.descriptor.document.WikiDescriptorDocumentHelper;
import org.xwiki.wiki.manager.WikiManager;
import org.xwiki.wiki.manager.WikiManagerException;
import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.doc.XWikiDocument;
public class WikiManagerScriptServiceTest
{
@Rule
public MockitoComponentMockingRule<WikiManagerScriptService> mocker =
new MockitoComponentMockingRule<WikiManagerScriptService>(WikiManagerScriptService.class);
private WikiManager wikiManager;
private WikiDescriptorManager wikiDescriptorManager;
private Provider<XWikiContext> xcontextProvider;
private Execution execution;
private AuthorizationManager authorizationManager;
private EntityReferenceSerializer<String> entityReferenceSerializer;
private ScriptServiceManager scriptServiceManager;
private StandardURLConfiguration standardURLConfiguration;
private WikiConfiguration wikiConfiguration;
private XWikiContext xcontext;
private ExecutionContext executionContext;
private DocumentReference currentUserRef;
private XWikiDocument currentDoc;
private WikiDescriptorDocumentHelper wikiDescriptorDocumentHelper;
@Before
public void setUp() throws Exception
{
wikiManager = mocker.getInstance(WikiManager.class);
wikiDescriptorManager = mocker.getInstance(WikiDescriptorManager.class);
authorizationManager = mocker.getInstance(AuthorizationManager.class);
scriptServiceManager = mocker.getInstance(ScriptServiceManager.class);
entityReferenceSerializer =
mocker.getInstance(new DefaultParameterizedType(null, EntityReferenceSerializer.class, String.class));
standardURLConfiguration = mocker.getInstance(StandardURLConfiguration.class);
wikiConfiguration = mocker.getInstance(WikiConfiguration.class);
xcontextProvider = mocker.registerMockComponent(XWikiContext.TYPE_PROVIDER);
xcontext = mock(XWikiContext.class);
when(xcontextProvider.get()).thenReturn(xcontext);
execution = mocker.getInstance(Execution.class);
executionContext = new ExecutionContext();
when(execution.getContext()).thenReturn(executionContext);
currentUserRef = new DocumentReference("mainWiki", "XWiki", "User");
when(xcontext.getUserReference()).thenReturn(currentUserRef);
currentDoc = mock(XWikiDocument.class);
when(xcontext.getDoc()).thenReturn(currentDoc);
when(wikiDescriptorManager.getMainWikiId()).thenReturn("mainWiki");
when(entityReferenceSerializer.serialize(currentUserRef)).thenReturn("mainWiki:XWiki.User");
wikiDescriptorDocumentHelper = mocker.getInstance(WikiDescriptorDocumentHelper.class);
}
/**
* @return the exception expected when the current script has the not the programing right
*/
private Exception currentScriptHasNotProgrammingRight() throws AccessDeniedException
{
DocumentReference authorDocRef = new DocumentReference("mainWiki", "XWiki", "Admin");
when(currentDoc.getAuthorReference()).thenReturn(authorDocRef);
DocumentReference currentDocRef = new DocumentReference("subwiki", "Test", "test");
when(currentDoc.getDocumentReference()).thenReturn(currentDocRef);
Exception exception = new AccessDeniedException(Right.PROGRAM, authorDocRef, currentDocRef);
doThrow(exception).when(authorizationManager).checkAccess(Right.PROGRAM, authorDocRef, currentDocRef);
return exception;
}
/**
* @return the exception expected when the current user has the not the admin right
*/
private Exception currentUserHasNotProgrammingRight() throws AccessDeniedException
{
WikiReference wiki = new WikiReference("mainWiki");
Exception exception = new AccessDeniedException(Right.PROGRAM, currentUserRef, wiki);
doThrow(exception).when(authorizationManager).checkAccess(eq(Right.PROGRAM), eq(currentUserRef), eq(wiki));
return exception;
}
/**
* @return the exception expected when the current user has the not the 'create wiki' right
*/
private Exception currentUserHasNotCreateWikiRight() throws AccessDeniedException
{
WikiReference wiki = new WikiReference("mainWiki");
Exception exception = new AccessDeniedException(Right.CREATE_WIKI, currentUserRef, wiki);
doThrow(exception).when(authorizationManager).checkAccess(eq(Right.CREATE_WIKI), eq(currentUserRef), eq(wiki));
return exception;
}
/**
* @param wikiId the id of the wiki for which to get the descriptor
* @return the wiki descriptor document for the wiki identified by the given wikiId
*/
private DocumentReference getAndSetupDescriptorDocument(String wikiId)
{
DocumentReference descriptorDocument =
new DocumentReference("mainWiki", "XWiki", "XWikiServer" + StringUtils.capitalize(wikiId));
when(wikiDescriptorDocumentHelper.getDocumentReferenceFromId(wikiId)).thenReturn(descriptorDocument);
return descriptorDocument;
}
@Test
public void get() throws Exception
{
// Test
mocker.getComponentUnderTest().get("template");
// Verify
verify(scriptServiceManager).get("wiki.template");
}
@Test
public void createWiki() throws Exception
{
WikiDescriptor descriptor = new WikiDescriptor("newiki", "alias");
when(wikiManager.create("newwiki", "alias", true)).thenReturn(descriptor);
WikiDescriptor result = mocker.getComponentUnderTest().createWiki("newwiki", "alias", "userA", true);
assertEquals(descriptor, result);
assertEquals("userA", result.getOwnerId());
verify(wikiDescriptorManager).saveDescriptor(result);
}
@Test
public void createWikiWithoutPR() throws Exception
{
Exception exception = currentScriptHasNotProgrammingRight();
WikiDescriptor result = mocker.getComponentUnderTest().createWiki("newwiki", "alias", "userA", true);
assertNull(result);
assertEquals(exception, mocker.getComponentUnderTest().getLastError());
}
@Test
public void createWikiWithoutCreateWikiRight() throws Exception
{
Exception exception = currentUserHasNotCreateWikiRight();
WikiDescriptor result = mocker.getComponentUnderTest().createWiki("newwiki", "alias", "userA", true);
assertNull(result);
assertEquals(exception, mocker.getComponentUnderTest().getLastError());
}
@Test
public void createWikiNoFailOnExistWithoutPR() throws Exception
{
Exception exception = currentUserHasNotProgrammingRight();
WikiDescriptor result = mocker.getComponentUnderTest().createWiki("newwiki", "alias", "userA", false);
assertNull(result);
assertEquals(exception, mocker.getComponentUnderTest().getLastError());
}
@Test
public void createWikiError() throws Exception
{
Exception exception = new WikiManagerException("error on create");
when(wikiManager.create("newwiki", "alias", true)).thenThrow(exception);
WikiDescriptor result = mocker.getComponentUnderTest().createWiki("newwiki", "alias", "userA", true);
assertNull(result);
assertEquals(exception, mocker.getComponentUnderTest().getLastError());
}
@Test
public void getByAlias() throws Exception
{
WikiDescriptor descriptor = new WikiDescriptor("wikiId", "wikiAlias");
when(wikiDescriptorManager.getByAlias("wikiAlias")).thenReturn(descriptor);
WikiDescriptor result = mocker.getComponentUnderTest().getByAlias("wikiAlias");
assertEquals(descriptor, result);
}
@Test
public void getByAliasError() throws Exception
{
Exception exception = new WikiManagerException("error in getByAlias");
when(wikiDescriptorManager.getByAlias("wikiAlias")).thenThrow(exception);
WikiDescriptor result = mocker.getComponentUnderTest().getByAlias("wikiAlias");
assertNull(result);
assertEquals(exception, mocker.getComponentUnderTest().getLastError());
}
@Test
public void getById() throws Exception
{
WikiDescriptor descriptor = new WikiDescriptor("wikiId", "wikiAlias");
when(wikiDescriptorManager.getById("wikiId")).thenReturn(descriptor);
WikiDescriptor result = mocker.getComponentUnderTest().getById("wikiId");
assertEquals(descriptor, result);
}
@Test
public void getByIdError() throws Exception
{
Exception exception = new WikiManagerException("error in getById");
when(wikiDescriptorManager.getById("wikiId")).thenThrow(exception);
WikiDescriptor result = mocker.getComponentUnderTest().getById("wikiId");
assertNull(result);
assertEquals(exception, mocker.getComponentUnderTest().getLastError());
}
@Test
public void getAll() throws Exception
{
WikiDescriptor descriptor1 = new WikiDescriptor("wikiId1", "wikiAlias1");
WikiDescriptor descriptor2 = new WikiDescriptor("wikiId2", "wikiAlias2");
Collection<WikiDescriptor> descriptors = new ArrayList<WikiDescriptor>();
descriptors.add(descriptor1);
descriptors.add(descriptor2);
when(wikiDescriptorManager.getAll()).thenReturn(descriptors);
Collection<WikiDescriptor> result = mocker.getComponentUnderTest().getAll();
assertEquals(descriptors, result);
}
@Test
public void getAllIds() throws Exception
{
Collection<String> wikiIds = Arrays.asList("wikiId1", "wikiId2");
when(wikiDescriptorManager.getAllIds()).thenReturn(wikiIds);
Collection<String> result = mocker.getComponentUnderTest().getAllIds();
assertEquals(wikiIds, result);
}
@Test
public void getAllError() throws Exception
{
Exception exception = new WikiManagerException("error in getAll");
when(wikiDescriptorManager.getAll()).thenThrow(exception);
Collection<WikiDescriptor> result = mocker.getComponentUnderTest().getAll();
assertTrue(result.isEmpty());
assertEquals(exception, mocker.getComponentUnderTest().getLastError());
}
@Test
public void getAllIdsError() throws Exception
{
Exception exception = new WikiManagerException("error in getAllIds");
when(wikiDescriptorManager.getAllIds()).thenThrow(exception);
Collection<String> result = mocker.getComponentUnderTest().getAllIds();
assertTrue(result.isEmpty());
assertEquals(exception, mocker.getComponentUnderTest().getLastError());
}
@Test
public void exists() throws Exception
{
when(wikiDescriptorManager.exists("wikiId")).thenReturn(true);
when(wikiDescriptorManager.exists("no")).thenReturn(false);
assertTrue(mocker.getComponentUnderTest().exists("wikiId"));
assertFalse(mocker.getComponentUnderTest().exists("no"));
}
@Test
public void existsError() throws Exception
{
Exception exception = new WikiManagerException("error in exists");
when(wikiDescriptorManager.exists("wikiId")).thenThrow(exception);
Boolean result = mocker.getComponentUnderTest().exists("wikiId");
assertNull(result);
assertEquals(exception, mocker.getComponentUnderTest().getLastError());
}
@Test
public void idAvailable() throws Exception
{
when(wikiManager.idAvailable("wikiId")).thenReturn(true);
when(wikiManager.idAvailable("no")).thenReturn(false);
assertTrue(mocker.getComponentUnderTest().idAvailable("wikiId"));
assertFalse(mocker.getComponentUnderTest().idAvailable("no"));
}
@Test
public void idAvailableError() throws Exception
{
Exception exception = new WikiManagerException("error in idAvailable");
when(wikiManager.idAvailable("wikiId")).thenThrow(exception);
Boolean result = mocker.getComponentUnderTest().idAvailable("wikiId");
assertNull(result);
assertEquals(exception, mocker.getComponentUnderTest().getLastError());
assertEquals(exception, mocker.getComponentUnderTest().getLastException());
}
@Test
public void getMainWikiDescriptor() throws Exception
{
WikiDescriptor descriptor = new WikiDescriptor("mainWiki", "wikiAlias");
when(wikiDescriptorManager.getMainWikiDescriptor()).thenReturn(descriptor);
WikiDescriptor result = mocker.getComponentUnderTest().getMainWikiDescriptor();
assertEquals(descriptor, result);
}
@Test
public void getMainWikiDescriptorError() throws Exception
{
Exception exception = new WikiManagerException("error in getMainWikiDescriptor");
when(wikiDescriptorManager.getMainWikiDescriptor()).thenThrow(exception);
WikiDescriptor result = mocker.getComponentUnderTest().getMainWikiDescriptor();
assertNull(result);
assertEquals(exception, mocker.getComponentUnderTest().getLastError());
}
@Test
public void getMainWikiId() throws Exception
{
String result = mocker.getComponentUnderTest().getMainWikiId();
assertEquals("mainWiki", result);
}
@Test
public void getCurrentWikiId() throws Exception
{
when(wikiDescriptorManager.getCurrentWikiId()).thenReturn("currentWiki");
String result = mocker.getComponentUnderTest().getCurrentWikiId();
assertEquals("currentWiki", result);
}
@Test
public void saveDescriptorWhenICanEditDescriptorDocument() throws Exception
{
WikiDescriptor oldDescriptor = new WikiDescriptor("wikiId", "wikiAlias");
oldDescriptor.setOwnerId("SomeUser");
when(wikiDescriptorManager.getById(oldDescriptor.getId())).thenReturn(oldDescriptor);
DocumentReference wikiDescriptorDocRef = getAndSetupDescriptorDocument(oldDescriptor.getId());
when(this.authorizationManager.hasAccess(Right.EDIT, currentUserRef, wikiDescriptorDocRef)).thenReturn(true);
// Changing some value, not the owner.
WikiDescriptor descriptor = new WikiDescriptor(oldDescriptor.getId(), "wikiAlias");
descriptor.setOwnerId(oldDescriptor.getOwnerId());
boolean result = mocker.getComponentUnderTest().saveDescriptor(descriptor);
assertTrue(result);
// The descriptor has been saved
verify(wikiDescriptorManager).saveDescriptor(descriptor);
}
@Test
public void saveDescriptorWhenIAmOwner() throws Exception
{
WikiDescriptor oldDescriptor = mock(WikiDescriptor.class);
when(oldDescriptor.getId()).thenReturn("wikiId");
when(oldDescriptor.getOwnerId()).thenReturn("mainWiki:XWiki.User");
when(wikiDescriptorManager.getById(oldDescriptor.getId())).thenReturn(oldDescriptor);
// Changing some value, not the owner.
WikiDescriptor descriptor = new WikiDescriptor(oldDescriptor.getId(), "wikiAlias");
descriptor.setOwnerId(oldDescriptor.getOwnerId());
boolean result = mocker.getComponentUnderTest().saveDescriptor(descriptor);
assertTrue(result);
// The owner of the old descriptor was verified (once by us, once by the call).
verify(oldDescriptor, times(2)).getOwnerId();
// The descriptor has been saved
verify(wikiDescriptorManager).saveDescriptor(descriptor);
}
@Test
public void saveDescriptorWhenIAmLocalAdmin() throws Exception
{
WikiDescriptor oldDescriptor = new WikiDescriptor("wikiId", "wikiAlias");
oldDescriptor.setOwnerId("SomeUser");
when(wikiDescriptorManager.getById(oldDescriptor.getId())).thenReturn(oldDescriptor);
// Local admin.
when(authorizationManager.hasAccess(eq(Right.ADMIN), eq(currentUserRef), eq(new WikiReference("wikiId"))))
.thenReturn(true);
// Changing some value, not the owner.
WikiDescriptor descriptor = new WikiDescriptor(oldDescriptor.getId(), "wikiAlias");
descriptor.setOwnerId(oldDescriptor.getOwnerId());
boolean result = mocker.getComponentUnderTest().saveDescriptor(descriptor);
assertTrue(result);
// The right has been checked
verify(authorizationManager).hasAccess(eq(Right.ADMIN), eq(currentUserRef), eq(new WikiReference("wikiId")));
// The descriptor has been saved
verify(wikiDescriptorManager).saveDescriptor(descriptor);
}
@Test
public void saveDescriptorWhenIAmNotOwnerNorLocalAdminNorGlobalAdmin() throws Exception
{
WikiDescriptor oldDescriptor = new WikiDescriptor("wikiId", "wikiAlias");
oldDescriptor.setOwnerId("SomeUser");
when(wikiDescriptorManager.getById(oldDescriptor.getId())).thenReturn(oldDescriptor);
when(authorizationManager.hasAccess(eq(Right.ADMIN), eq(currentUserRef), eq(new WikiReference("wikiId"))))
.thenReturn(false);
// Changing some value, not the owner.
WikiDescriptor descriptor = new WikiDescriptor(oldDescriptor.getId(), "wikiAlias");
oldDescriptor.setOwnerId(oldDescriptor.getOwnerId());
boolean result = mocker.getComponentUnderTest().saveDescriptor(descriptor);
assertFalse(result);
// The descriptor has not been saved
verify(wikiDescriptorManager, never()).saveDescriptor(descriptor);
Exception exception = new AccessDeniedException(currentUserRef, new WikiReference("wikiId"));
assertEquals(exception.getMessage(), mocker.getComponentUnderTest().getLastError().getMessage());
assertEquals(exception.getClass(), mocker.getComponentUnderTest().getLastError().getClass());
}
@Test
public void saveDescriptorWhenIAmLocalAdminAndChangeOwner() throws Exception
{
WikiDescriptor oldDescriptor = new WikiDescriptor("wikiId", "wikiAlias");
oldDescriptor.setOwnerId("SomeUser");
when(wikiDescriptorManager.getById(oldDescriptor.getId())).thenReturn(oldDescriptor);
// Changing the owner.
WikiDescriptor descriptor = new WikiDescriptor(oldDescriptor.getId(), "wikiAlias");
descriptor.setOwnerId("SomeOtherUserOrMyself");
boolean result = mocker.getComponentUnderTest().saveDescriptor(descriptor);
assertFalse(result);
// The right has been checked
verify(authorizationManager).hasAccess(eq(Right.ADMIN), eq(currentUserRef), eq(new WikiReference("wikiId")));
// The descriptor has not been saved
verify(wikiDescriptorManager, never()).saveDescriptor(descriptor);
Exception expectedException = new AccessDeniedException(currentUserRef, new WikiReference("wikiId"));
assertEquals(expectedException.getMessage(), mocker.getComponentUnderTest().getLastError().getMessage());
assertEquals(expectedException.getClass(), mocker.getComponentUnderTest().getLastError().getClass());
}
@Test
public void saveDescriptorWhenICanEditDescriptorDocumentAndChangeOwner() throws Exception
{
WikiDescriptor oldDescriptor = new WikiDescriptor("wikiId", "wikiAlias");
oldDescriptor.setOwnerId("SomeUser");
when(wikiDescriptorManager.getById(oldDescriptor.getId())).thenReturn(oldDescriptor);
DocumentReference wikiDescriptorDocRef = getAndSetupDescriptorDocument(oldDescriptor.getId());
when(this.authorizationManager.hasAccess(Right.EDIT, currentUserRef, wikiDescriptorDocRef)).thenReturn(true);
// Changing the owner is possible, since I can directly edit the wiki descriptor anyway.
WikiDescriptor descriptor = new WikiDescriptor(oldDescriptor.getId(), "wikiAlias");
descriptor.setOwnerId("SomeOtherUserOrMyself");
boolean result = mocker.getComponentUnderTest().saveDescriptor(descriptor);
assertTrue(result);
// The descriptor has been saved
verify(wikiDescriptorManager).saveDescriptor(descriptor);
}
@Test
public void saveDescriptorWhenDescriptorDidNotExist() throws Exception
{
WikiDescriptor descriptor = new WikiDescriptor("wikiId", "wikiAlias");
boolean result = mocker.getComponentUnderTest().saveDescriptor(descriptor);
assertFalse(result);
// Verify the rights have been checked
verify(authorizationManager).hasAccess(eq(Right.ADMIN), eq(currentUserRef), eq(new WikiReference("mainWiki")));
// The descriptor has not been saved
verify(wikiDescriptorManager, never()).saveDescriptor(descriptor);
}
@Test
public void saveDescriptorWhenDescriptorDidNotExistAndIAmGlobalAdmin() throws Exception
{
when(this.authorizationManager.hasAccess(Right.ADMIN, currentUserRef, new WikiReference("mainWiki")))
.thenReturn(true);
WikiDescriptor descriptor = new WikiDescriptor("wikiId", "wikiAlias");
boolean result = mocker.getComponentUnderTest().saveDescriptor(descriptor);
assertTrue(result);
// Verify the rights have been checked
verify(authorizationManager).hasAccess(eq(Right.ADMIN), eq(currentUserRef), eq(new WikiReference("mainWiki")));
// The descriptor has been saved
verify(wikiDescriptorManager).saveDescriptor(descriptor);
}
@Test
public void isPathMode() throws Exception
{
when(standardURLConfiguration.isPathBasedMultiWiki()).thenReturn(true);
assertTrue(mocker.getComponentUnderTest().isPathMode());
when(standardURLConfiguration.isPathBasedMultiWiki()).thenReturn(false);
assertFalse(mocker.getComponentUnderTest().isPathMode());
}
@Test
public void getAliasSuffix() throws Exception
{
when(wikiConfiguration.getAliasSuffix()).thenReturn("mysuffix.org");
assertEquals(mocker.getComponentUnderTest().getAliasSuffix(), "mysuffix.org");
}
@Test
public void getCurrentDescriptor() throws Exception
{
mocker.getComponentUnderTest().getCurrentWikiDescriptor();
verify(wikiDescriptorManager).getCurrentWikiDescriptor();
}
}