/*!
* Copyright 2010 - 2016 Pentaho Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.pentaho.di.repository.pur;
import org.junit.After;
import org.junit.Before;
import org.pentaho.di.core.KettleEnvironment;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.repository.RepositoryTestLazySupport;
import org.pentaho.platform.api.engine.IAuthorizationPolicy;
import org.pentaho.platform.api.engine.IPentahoSession;
import org.pentaho.platform.api.engine.security.userroledao.IPentahoRole;
import org.pentaho.platform.api.engine.security.userroledao.IPentahoUser;
import org.pentaho.platform.api.engine.security.userroledao.IUserRoleDao;
import org.pentaho.platform.api.mt.ITenant;
import org.pentaho.platform.api.mt.ITenantManager;
import org.pentaho.platform.api.mt.ITenantedPrincipleNameResolver;
import org.pentaho.platform.api.repository2.unified.IRepositoryVersionManager;
import org.pentaho.platform.api.repository2.unified.IUnifiedRepository;
import org.pentaho.platform.engine.core.system.PentahoSessionHolder;
import org.pentaho.platform.engine.core.system.StandaloneSession;
import org.pentaho.platform.repository2.unified.IRepositoryFileDao;
import org.pentaho.platform.repository2.unified.ServerRepositoryPaths;
import org.pentaho.platform.repository2.unified.jcr.JcrRepositoryFileUtils;
import org.pentaho.platform.repository2.unified.jcr.RepositoryFileProxyFactory;
import org.pentaho.platform.repository2.unified.jcr.SimpleJcrTestUtils;
import org.pentaho.platform.repository2.unified.jcr.jackrabbit.security.TestPrincipalProvider;
import org.pentaho.platform.repository2.unified.jcr.sejcr.CredentialsStrategy;
import org.pentaho.platform.security.policy.rolebased.IRoleAuthorizationPolicyRoleBindingDao;
import org.pentaho.platform.security.userroledao.DefaultTenantedPrincipleNameResolver;
import org.pentaho.test.platform.engine.core.MicroPlatform;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.extensions.jcr.JcrTemplate;
import org.springframework.extensions.jcr.SessionFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestContextManager;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.support.DirtiesContextTestExecutionListener;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import javax.jcr.Repository;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* @author Andrey Khayrutdinov
*/
@ContextConfiguration( locations = { "classpath:/repository.spring.xml",
"classpath:/repository-test-override.spring.xml", "classpath:/pdi-pur-plugin-test-override.spring.xml" } )
@TestExecutionListeners( listeners = { DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class, TransactionalTestExecutionListener.class } )
public abstract class PurRepositoryTestBase extends RepositoryTestLazySupport implements ApplicationContextAware {
protected static final String TEST_LOGIN = "tester";
protected static final String TEST_TENANT = "testTenant";
protected static final String ANONYMOUS_ROLE = "Anonymous";
// protected fields are useful for heirs
protected IUnifiedRepository unifiedRepository;
protected PurRepository purRepository;
// these values are picked up from the Spring context to be used or injected into the micro platform
private String superAdminRole;
private String repositoryAdmin;
private String systemAdmin;
private String tenantAdminRole;
private String tenantAuthenticatedRole;
private ITenantManager tenantManager;
private IUserRoleDao userRoleDao;
private IAuthorizationPolicy authorizationPolicy;
private IRoleAuthorizationPolicyRoleBindingDao roleBindingDaoTarget;
private JcrTemplate testJcrTemplate;
private IRepositoryFileDao repositoryFileDao;
private TransactionTemplate txnTemplate;
// these two instances are just injected into the micro platform
// they do not store anything except their settings, hence can be shared among different executions of tests
private final ITenantedPrincipleNameResolver userNameUtils = new DefaultTenantedPrincipleNameResolver();
private final ITenantedPrincipleNameResolver roleNameUtils = new DefaultTenantedPrincipleNameResolver(
DefaultTenantedPrincipleNameResolver.ALTERNATE_DELIMETER );
// these objects are created during environment initialisation
private ITenant systemTenant;
private ITenant testingTenant;
// this block stores those values, that should be restored after test's execution
private MicroPlatform mp;
private IRepositoryVersionManager existingVersionManager;
private TestContextManager testContextManager;
public PurRepositoryTestBase( Boolean lazyRepo ) {
super( lazyRepo );
}
@Before
public void setUp() throws Exception {
this.testContextManager = new TestContextManager( getClass() );
this.testContextManager.prepareTestInstance( this );
KettleEnvironment.init();
PentahoSessionHolder.setStrategyName( PentahoSessionHolder.MODE_GLOBAL );
mockVersionManager();
removePentahoRootFolder();
startMicroPlatform();
createSystemUser();
createTester();
createPurRepository();
loginAsTester();
}
private void mockVersionManager() {
existingVersionManager = JcrRepositoryFileUtils.getRepositoryVersionManager();
IRepositoryVersionManager versionManager = mock( IRepositoryVersionManager.class );
when( versionManager.isVersioningEnabled( anyString() ) ).thenReturn( true );
when( versionManager.isVersionCommentEnabled( anyString() ) ).thenReturn( false );
JcrRepositoryFileUtils.setRepositoryVersionManager( versionManager );
}
private void removePentahoRootFolder() {
loginAsRepositoryAdmin();
SimpleJcrTestUtils.deleteItem( testJcrTemplate, ServerRepositoryPaths.getPentahoRootFolderPath() );
}
protected void loginAsRepositoryAdmin() {
StandaloneSession repositoryAdminSession = PurRepositoryTestingUtils.createSession( repositoryAdmin );
Authentication repositoryAdminAuthentication = PurRepositoryTestingUtils.createAuthentication( repositoryAdmin,
superAdminRole );
PurRepositoryTestingUtils.setSession( repositoryAdminSession, repositoryAdminAuthentication );
}
private void startMicroPlatform() throws Exception {
mp = new MicroPlatform();
mp.defineInstance( "tenantedUserNameUtils", userNameUtils );
mp.defineInstance( "tenantedRoleNameUtils", roleNameUtils );
mp.defineInstance( IAuthorizationPolicy.class, authorizationPolicy );
mp.defineInstance( ITenantManager.class, tenantManager );
mp.defineInstance( "roleAuthorizationPolicyRoleBindingDaoTarget", roleBindingDaoTarget );
mp.defineInstance( "repositoryAdminUsername", repositoryAdmin );
mp.defineInstance( "RepositoryFileProxyFactory",
new RepositoryFileProxyFactory( testJcrTemplate, repositoryFileDao ) );
mp.defineInstance( "useMultiByteEncoding", Boolean.FALSE );
initMicroPlatform( mp );
mp.start();
}
protected void initMicroPlatform( MicroPlatform mp ) {
// override this method to inject your own values into the micro platform
}
private void createSystemUser() {
loginAsRepositoryAdmin();
setAclManagement();
systemTenant =
tenantManager.createTenant( null, ServerRepositoryPaths.getPentahoRootFolderName(), tenantAdminRole,
tenantAuthenticatedRole, ANONYMOUS_ROLE );
userRoleDao.createUser( systemTenant, systemAdmin, "", "", new String[] { tenantAdminRole } );
}
private void setAclManagement() {
testJcrTemplate.execute( PurRepositoryTestingUtils.setAclManagementCallback() );
}
private void createTester() {
loginAsSystemAdmin();
testingTenant =
tenantManager
.createTenant( systemTenant, TEST_TENANT, tenantAdminRole, tenantAuthenticatedRole, ANONYMOUS_ROLE );
userRoleDao.createUser( testingTenant, TEST_LOGIN, "", "", new String[] { tenantAdminRole } );
createUserHomeFolder( testingTenant, TEST_LOGIN );
}
private void loginAsSystemAdmin() {
StandaloneSession session = PurRepositoryTestingUtils.createSession( systemTenant, systemAdmin );
Authentication auth = PurRepositoryTestingUtils.createAuthentication( systemAdmin, tenantAdminRole,
tenantAuthenticatedRole );
PurRepositoryTestingUtils.setSession( session, auth );
}
private void createUserHomeFolder( final ITenant theTenant, final String theUsername ) {
IPentahoSession origPentahoSession = PentahoSessionHolder.getSession();
Authentication origAuthentication = SecurityContextHolder.getContext().getAuthentication();
String principleId = userNameUtils.getPrincipleId( theTenant, theUsername );
String authenticatedRoleId = roleNameUtils.getPrincipleId( theTenant, tenantAuthenticatedRole );
TransactionCallbackWithoutResult callback =
PurRepositoryTestingUtils.createUserHomeDirCallback( theTenant, theUsername, principleId, authenticatedRoleId,
repositoryFileDao );
try {
loginAsRepositoryAdmin();
txnTemplate.execute( callback );
} finally {
PurRepositoryTestingUtils.setSession( origPentahoSession, origAuthentication );
}
}
protected void createPurRepository() throws KettleException {
PurRepositoryMeta purMeta = new PurRepositoryMeta();
purMeta.setName( "JackRabbit" );
purMeta.setDescription( "Jackrabbit test repository" );
purRepository = new PurRepository();
purRepository.init( purMeta );
purRepository.setTest( unifiedRepository );
purRepository.setPurRepositoryConnector( new PurRepositoryConnector( purRepository, purMeta, purRepository
.getRootRef() ) );
purRepository.connect( TEST_LOGIN, "" );
}
private void loginAsTester() throws Exception {
Authentication authentication =
PurRepositoryTestingUtils.createAuthentication( TEST_LOGIN, tenantAuthenticatedRole,
roleNameUtils.getPrincipleId( testingTenant, ANONYMOUS_ROLE ) );
StandaloneSession session = PurRepositoryTestingUtils.createSession( testingTenant, TEST_LOGIN );
session.setAttribute( "SECURITY_PRINCIPAL", authentication );
PurRepositoryTestingUtils.setSession( session, authentication );
}
@After
public void tearDown() throws Exception {
cleanupUserAndRoles( testingTenant );
cleanupUserAndRoles( systemTenant );
unifiedRepository = null;
purRepository = null;
superAdminRole = repositoryAdmin = systemAdmin = tenantAdminRole = tenantAuthenticatedRole = null;
tenantManager = null;
userRoleDao = null;
authorizationPolicy = null;
roleBindingDaoTarget = null;
testJcrTemplate = null;
repositoryFileDao = null;
txnTemplate = null;
systemTenant = testingTenant = null;
mp.stop();
mp = null;
JcrRepositoryFileUtils.setRepositoryVersionManager( existingVersionManager );
PentahoSessionHolder.setStrategyName( PentahoSessionHolder.MODE_INHERITABLETHREADLOCAL );
}
private void cleanupUserAndRoles( final ITenant tenant ) {
loginAsRepositoryAdmin();
for ( IPentahoRole role : userRoleDao.getRoles( tenant ) ) {
userRoleDao.deleteRole( role );
}
for ( IPentahoUser user : userRoleDao.getUsers( tenant ) ) {
userRoleDao.deleteUser( user );
}
}
@Override
public void setApplicationContext( ApplicationContext applicationContext ) throws BeansException {
unifiedRepository = applicationContext.getBean( "unifiedRepository", IUnifiedRepository.class );
tenantManager = applicationContext.getBean( "tenantMgrProxy", ITenantManager.class );
userRoleDao = applicationContext.getBean( "userRoleDao", IUserRoleDao.class );
authorizationPolicy = applicationContext.getBean( "authorizationPolicy", IAuthorizationPolicy.class );
roleBindingDaoTarget =
(IRoleAuthorizationPolicyRoleBindingDao) applicationContext
.getBean( "roleAuthorizationPolicyRoleBindingDaoTarget" );
SessionFactory jcrSessionFactory = (SessionFactory) applicationContext.getBean( "jcrSessionFactory" );
testJcrTemplate = new JcrTemplate( jcrSessionFactory );
testJcrTemplate.setAllowCreate( true );
testJcrTemplate.setExposeNativeSession( true );
txnTemplate = applicationContext.getBean( "jcrTransactionTemplate", TransactionTemplate.class );
repositoryFileDao = (IRepositoryFileDao) applicationContext.getBean( "repositoryFileDao" );
superAdminRole = applicationContext.getBean( "superAdminAuthorityName", String.class );
repositoryAdmin = applicationContext.getBean( "repositoryAdminUsername", String.class );
systemAdmin = (String) applicationContext.getBean( "superAdminUserName" );
tenantAdminRole = applicationContext.getBean( "singleTenantAdminAuthorityName", String.class );
tenantAuthenticatedRole = applicationContext.getBean( "singleTenantAuthenticatedAuthorityName", String.class );
TestPrincipalProvider.userRoleDao = userRoleDao;
TestPrincipalProvider.adminCredentialsStrategy =
(CredentialsStrategy) applicationContext.getBean( "jcrAdminCredentialsStrategy" );
TestPrincipalProvider.repository = (Repository) applicationContext.getBean( "jcrRepository" );
doSetApplicationContext( applicationContext );
}
protected void doSetApplicationContext( ApplicationContext applicationContext ) {
// override this method to pick up what is needed from the context
}
}