/*!
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program 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.
*
* Copyright (c) 2002-2016 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.platform.repository2.unified.jcr;
import org.apache.jackrabbit.core.VersionManagerImpl;
import org.junit.Before;
import org.junit.Test;
import org.pentaho.platform.api.engine.IPentahoSession;
import org.pentaho.platform.api.repository2.unified.IRepositoryAccessVoterManager;
import org.pentaho.platform.api.repository2.unified.IRepositoryFileData;
import org.pentaho.platform.api.repository2.unified.IRepositoryVersionManager;
import org.pentaho.platform.api.repository2.unified.RepositoryFile;
import org.pentaho.platform.api.repository2.unified.RepositoryFilePermission;
import org.pentaho.platform.engine.core.system.PentahoSessionHolder;
import org.pentaho.platform.engine.core.system.PentahoSystem;
import org.pentaho.platform.repository2.unified.IRepositoryFileAclDao;
import org.springframework.dao.DataAccessException;
import org.springframework.extensions.jcr.JcrCallback;
import org.springframework.extensions.jcr.JcrTemplate;
import javax.jcr.AccessDeniedException;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Workspace;
import java.util.Collections;
import java.util.List;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.*;
public class JcrRepositoryFileDaoTest {
private JcrRepositoryFileDao dao;
private IRepositoryAccessVoterManager accessVoterManager;
private IPentahoSession pentahoSession;
@Before
public void setUp() throws RepositoryException {
Node node = mock( Node.class );
Node nodeParent = mock( Node.class );
when( node.getIdentifier() ).thenReturn( "" );
when( nodeParent.getIdentifier() ).thenReturn( "" );
when( node.getParent() ).thenReturn( nodeParent );
when( node.isNodeType( "null:pentahoFile" ) ).thenReturn( true );
when( node.isNodeType( "null:pentahoVersionable" ) ).thenReturn( true );
VersionManagerImpl versionManager = mock( VersionManagerImpl.class );
Workspace workspace = mock( Workspace.class );
when( workspace.getVersionManager() ).thenReturn( versionManager );
Session session = mock( Session.class );
when( session.getWorkspace() ).thenReturn( workspace );
when( session.getNodeByIdentifier( anyString() ) ).thenReturn( node );
when( session.getItem( anyString() ) ).thenReturn( node );
pentahoSession = mock( IPentahoSession.class );
PentahoSessionHolder.setSession( pentahoSession );
IRepositoryVersionManager repositoryVersionManager = mock( IRepositoryVersionManager.class );
when( repositoryVersionManager.isVersioningEnabled( anyString() ) ).thenReturn( true );
PentahoSystem.registerObject( repositoryVersionManager );
JcrTemplate jcrTemplate = new JcrTemplate() {
@Override
public Object execute( JcrCallback callback ) throws DataAccessException {
try {
return callback.doInJcr( session );
} catch ( Exception e ) {
// wrapping exception to comply overriding rules
throw new RuntimeException( e );
}
}
};
List<ITransformer<IRepositoryFileData>> transformerList = Collections.emptyList();
IPathConversionHelper pathConversionHelper = new DefaultPathConversionHelper();
IRepositoryFileAclDao aclDao = mock( IRepositoryFileAclDao.class );
accessVoterManager = mock( IRepositoryAccessVoterManager.class );
JcrRepositoryFileDao jcrDao = new JcrRepositoryFileDao( jcrTemplate, transformerList, null, null,
pathConversionHelper, aclDao, null, accessVoterManager );
dao = spy( jcrDao );
}
@Test
public void shouldConsultAccessVoterWhenCopyingOrMovingFiles() {
RepositoryFile filePermitted = mock( RepositoryFile.class );
RepositoryFile fileNotPermitted = mock( RepositoryFile.class );
RepositoryFile destinationPermitted = mock( RepositoryFile.class );
RepositoryFile destinationNotPermitted = mock( RepositoryFile.class );
doReturn( filePermitted ).when( dao ).getFileById( "/filePermitted" );
doReturn( fileNotPermitted ).when( dao ).getFileById( "/fileNotPermitted" );
doReturn( destinationPermitted ).when( dao ).getFile( "/destinationPermitted" );
doReturn( destinationNotPermitted ).when( dao ).getFile( "/destinationNotPermitted" );
doReturn( true ).when( accessVoterManager )
.hasAccess( filePermitted, RepositoryFilePermission.WRITE, null, pentahoSession );
doReturn( false ).when( accessVoterManager )
.hasAccess( fileNotPermitted, RepositoryFilePermission.WRITE, null, pentahoSession );
doReturn( true ).when( accessVoterManager )
.hasAccess( destinationPermitted, RepositoryFilePermission.WRITE, null, pentahoSession );
doReturn( false ).when( accessVoterManager )
.hasAccess( destinationNotPermitted, RepositoryFilePermission.WRITE, null, pentahoSession );
// should move the file,
// if the user has write permissions to the source file,
// and write permissions to the destination folder.
try {
dao.moveFile( "/filePermitted", "/destinationPermitted", null );
} catch ( Throwable e ) {
fail( e.getMessage() );
}
// should NOT move the file and throw an exception,
// if the user has write permissions to the destination folder,
// but does not have write permissions to the source file.
try {
dao.moveFile( "/fileNotPermitted", "/destinationPermitted", null );
} catch ( Throwable e ) {
// unwrap original exception and check it
if ( !( e instanceof RuntimeException )
|| !( e.getCause() instanceof AccessDeniedException ) ) {
fail( e.getMessage() );
}
}
// should NOT move the file and throw an exception,
// if the user has write permissions to the source file,
// but does not have write permissions to the destination folder.
try {
dao.moveFile( "/filePermitted", "/destinationNotPermitted", null );
} catch ( Throwable e ) {
// unwrap original exception and check it
if ( !( e instanceof RuntimeException )
|| !( e.getCause() instanceof AccessDeniedException ) ) {
fail( e.getMessage() );
}
}
// should NOT move the file and throw an exception,
// if the user neither has write permissions to the source file,
// nor has write permissions to the destination folder.
try {
dao.moveFile( "/fileNotPermitted", "/destinationNotPermitted", null );
} catch ( Throwable e ) {
// unwrap original exception and check it
if ( !( e instanceof RuntimeException )
|| !( e.getCause() instanceof AccessDeniedException ) ) {
fail( e.getMessage() );
}
}
}
}