/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, version 2 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.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 General Public License for more details.
*
*
* Copyright 2006 - 2013 Pentaho Corporation. All rights reserved.
*/
package org.pentaho.platform.dataaccess.datasource.wizard;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.core.Response;
import junit.framework.Assert;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.junit.Before;
import org.junit.Test;
import org.pentaho.database.model.DatabaseConnection;
import org.pentaho.database.model.IDatabaseConnection;
import org.pentaho.database.service.DatabaseDialectService;
import org.pentaho.database.service.IDatabaseDialectService;
import org.pentaho.platform.api.engine.IAuthorizationPolicy;
import org.pentaho.platform.api.engine.ICacheManager;
import org.pentaho.platform.api.engine.IPentahoDefinableObjectFactory.Scope;
import org.pentaho.platform.api.engine.IPentahoSession;
import org.pentaho.platform.api.engine.IUserRoleListService;
import org.pentaho.platform.api.mt.ITenant;
import org.pentaho.platform.api.repository2.unified.IBackingRepositoryLifecycleManager;
import org.pentaho.platform.api.repository2.unified.IUnifiedRepository;
import org.pentaho.platform.api.util.IPasswordService;
import org.pentaho.platform.dataaccess.datasource.wizard.service.impl.DatasourceResource;
import org.pentaho.platform.dataaccess.datasource.wizard.service.impl.MetadataDatasourceService;
import org.pentaho.platform.engine.core.system.PentahoSessionHolder;
import org.pentaho.platform.engine.core.system.StandaloneSession;
import org.pentaho.platform.engine.core.system.SystemSettings;
import org.pentaho.platform.plugin.action.mondrian.catalog.IMondrianCatalogService;
import org.pentaho.platform.plugin.action.mondrian.catalog.MondrianCatalogHelper;
import org.pentaho.platform.plugin.services.cache.CacheManager;
import org.pentaho.platform.repository2.unified.DefaultUnifiedRepository;
import org.pentaho.platform.util.Base64PasswordService;
import org.pentaho.test.platform.MethodTrackingData;
import org.pentaho.test.platform.engine.core.MicroPlatform;
import org.pentaho.test.platform.engine.security.MockSecurityHelper;
import org.springframework.context.ApplicationContextAware;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
/**
* Integration test. Tests {@link DefaultUnifiedRepository} and
* {@link IAuthorizationPolicy} fully configured behind Spring Security's method
* security and Spring's transaction interceptor.
*
* <p>
* Note the RunWith annotation that uses a special runner that knows how to
* setup a Spring application context. The application context config files are
* listed in the ContextConfiguration annotation. By implementing
* {@link ApplicationContextAware}, this unit test can access various beans
* defined in the application context, including the bean under test.
* </p>
*
* @author mlowery
*/
@SuppressWarnings("nls")
public class DatasourceWebServicesSecurityTest {
private String tenantAdminAuthorityNamePattern = "{0}_Admin";
private String tenantAuthenticatedAuthorityNamePattern = "{0}_Authenticated";
private static final String USER_PARAMETER = "user";
private IBackingRepositoryLifecycleManager manager;
private Mockery context = new JUnit4Mockery();
private IUnifiedRepository repo;
private MicroPlatform booter;
@Before
public void setUp() throws Exception {
manager = new MockBackingRepositoryLifecycleManager(new MockSecurityHelper());
repo = context.mock(IUnifiedRepository.class);
booter = new MicroPlatform("target/test-classes/solution1");
booter.define(IPasswordService.class, Base64PasswordService.class, Scope.GLOBAL);
booter.define(IDatabaseConnection.class, DatabaseConnection.class, Scope.GLOBAL);
booter.define(IDatabaseDialectService.class, DatabaseDialectService.class, Scope.GLOBAL);
booter.define(IMondrianCatalogService.class, MondrianCatalogHelper.class, Scope.GLOBAL);
booter.define(ICacheManager.class, CacheManager.class, Scope.GLOBAL);
booter.defineInstance(IUserRoleListService.class, context.mock(IUserRoleListService.class));
final IAuthorizationPolicy policy = context.mock(IAuthorizationPolicy.class);
booter.defineInstance(IAuthorizationPolicy.class, policy);
booter.defineInstance(IUnifiedRepository.class, repo);
booter.setSettingsProvider(new SystemSettings());
booter.start();
context.checking(new Expectations() {{
oneOf (policy); will(returnValue(false));
oneOf (policy); will(returnValue(false));
oneOf (policy); will(returnValue(false));
}});
PentahoSessionHolder.setStrategyName(PentahoSessionHolder.MODE_GLOBAL);
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_GLOBAL);
}
// TODO This is a broken test, we are providing null as input stream to postMondrianSchema
@Test
public void testPostMondrainSchema() throws Exception {
login("joe", "duff", false);
//Response res = analysisDatasourceService.postMondrainSchema(null, schemaFileInfo, catalogName, datasourceName, overwrite, xmlaEnabledFlag, parameters);
//Assert.assertTrue(res.getEntity().equals("org.pentaho.platform.api.engine.PentahoAccessControlException: Access Denied"));
//Assert.assertTrue(res.getEntity().equals("Access Denied"));
logout();
}
@Test
public void testPutMondrainSchema() throws Exception {
login("joe", "duff", false);
//analysisDatasourceService.importAnalysisSchemaFile(domainId, dataInputStream, domainId, "true","false");
//Assert.assertTrue(res.getEntity().equals("Access Denied"));
//res = analysisDatasourceService.postMondrainSchema(dataInputStream, schemaFileInfo, domainId, datasourceName, overwrite, xmlaEnabledFlag, parameters);
//Assert.assertTrue(res.getEntity().equals("org.pentaho.platform.api.engine.PentahoAccessControlException: Access Denied"));
logout();
}
@Test
public void testImportMetadataDatasource() throws Exception {
login("joe", "duff", false);
MetadataDatasourceService analysisDatasourceService = new MetadataDatasourceService();
Response res = analysisDatasourceService.storeDomain(null, null);
Assert.assertTrue(res.getEntity().equals("org.pentaho.platform.api.engine.PentahoAccessControlException: Access Denied"));
// res = analysisDatasourceService.importMetadataDatasourceLegacy(null, null, null);
Assert.assertTrue(res.getEntity().equals("org.pentaho.platform.api.engine.PentahoAccessControlException: Access Denied"));
res = analysisDatasourceService.addLocalizationFile(null, null, null);
Assert.assertTrue(res.getEntity().equals("org.pentaho.platform.api.engine.PentahoAccessControlException: Access Denied"));
logout();
}
/*
* RPB: Removed this test. It does not seem to test anything particular that has to do with the data access plugin.
@Test
public void testRepositoryImportResource() throws Exception {
login("joe", "duff", false);
RepositoryImportResource repositoryImportResource = new RepositoryImportResource();
Response res = repositoryImportResource.doPostImport(
(String)null,
(InputStream)null,
(String)null,
(String)null,
(String)null,
(String)null,
(FormDataContentDisposition)null
);
Assert.assertTrue(res.getEntity().equals("org.pentaho.platform.api.engine.PentahoAccessControlException: Access Denied"));
logout();
}
*/
protected void login(final String username, final String tenantId, final boolean tenantAdmin) {
StandaloneSession pentahoSession = new StandaloneSession(username);
pentahoSession.setAuthenticated(username);
pentahoSession.setAttribute(IPentahoSession.TENANT_ID_KEY, tenantId);
final String password = "password";
List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>();
authList.add(new SimpleGrantedAuthority(MessageFormat.format(tenantAuthenticatedAuthorityNamePattern, tenantId)));
if (tenantAdmin) {
authList.add(new SimpleGrantedAuthority(MessageFormat.format(tenantAdminAuthorityNamePattern, tenantId)));
}
UserDetails userDetails = new User(username, password, true, true, true, true, authList);
Authentication auth = new UsernamePasswordAuthenticationToken(userDetails, password, authList);
PentahoSessionHolder.setSession(pentahoSession);
// this line necessary for Spring Security's MethodSecurityInterceptor
SecurityContextHolder.getContext().setAuthentication(auth);
manager.newTenant();
manager.newUser();
}
protected void logout() {
PentahoSessionHolder.removeSession();
SecurityContextHolder.getContext().setAuthentication(null);
}
private class MockBackingRepositoryLifecycleManager implements IBackingRepositoryLifecycleManager {
public static final String UNIT_TEST_EXCEPTION_MESSAGE = "Unit Test Exception";
private ArrayList<MethodTrackingData> methodTrackerHistory = new ArrayList<MethodTrackingData>();
private boolean throwException = false;
private MockSecurityHelper securityHelper;
private MockBackingRepositoryLifecycleManager(final MockSecurityHelper securityHelper) {
assert (null != securityHelper);
this.securityHelper = securityHelper;
}
public void startup() {
methodTrackerHistory.add(new MethodTrackingData("startup")
.addParameter(USER_PARAMETER, securityHelper.getCurrentUser()));
if (throwException) throw new RuntimeException(UNIT_TEST_EXCEPTION_MESSAGE);
}
public void shutdown() {
methodTrackerHistory.add(new MethodTrackingData("shutdown")
.addParameter(USER_PARAMETER, securityHelper.getCurrentUser()));
if (throwException) throw new RuntimeException(UNIT_TEST_EXCEPTION_MESSAGE);
}
public void newTenant(final ITenant tenant) {
methodTrackerHistory.add(new MethodTrackingData("newTenant")
.addParameter(USER_PARAMETER, securityHelper.getCurrentUser())
.addParameter("tenant", tenant));
if (throwException) throw new RuntimeException(UNIT_TEST_EXCEPTION_MESSAGE);
}
public void newTenant() {
methodTrackerHistory.add(new MethodTrackingData("newTenant")
.addParameter(USER_PARAMETER, securityHelper.getCurrentUser()));
if (throwException) throw new RuntimeException(UNIT_TEST_EXCEPTION_MESSAGE);
}
public void newUser(final ITenant tenant, final String username) {
methodTrackerHistory.add(new MethodTrackingData("newUser")
.addParameter(USER_PARAMETER, securityHelper.getCurrentUser())
.addParameter("tenant", tenant)
.addParameter("username", username));
if (throwException) throw new RuntimeException(UNIT_TEST_EXCEPTION_MESSAGE);
}
public void newUser() {
methodTrackerHistory.add(new MethodTrackingData("newUser")
.addParameter(USER_PARAMETER, securityHelper.getCurrentUser()));
if (throwException) throw new RuntimeException(UNIT_TEST_EXCEPTION_MESSAGE);
}
@Override
public void addMetadataToRepository(String arg0) {
// TODO Auto-generated method stub
}
@Override
public Boolean doesMetadataExists(String arg0) {
// TODO Auto-generated method stub
return null;
}
}
}