org.pentaho.test.platform.web.http.api.DirectoryResourceIT.java Source code

Java tutorial

Introduction

Here is the source code for org.pentaho.test.platform.web.http.api.DirectoryResourceIT.java

Source

/*!
 * 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.test.platform.web.http.api;

import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM;
import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.fail;
import static org.pentaho.test.platform.web.http.api.JerseyTestUtil.assertResponse;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.jcr.Repository;
import javax.ws.rs.core.Response;

import junit.framework.TestCase;

import org.apache.commons.io.FileUtils;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.pentaho.platform.api.engine.IAuthorizationPolicy;
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.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.IBackingRepositoryLifecycleManager;
import org.pentaho.platform.api.repository2.unified.IRepositoryVersionManager;
import org.pentaho.platform.api.repository2.unified.IUnifiedRepository;
import org.pentaho.platform.core.mt.Tenant;
import org.pentaho.platform.engine.core.system.PentahoSessionHolder;
import org.pentaho.platform.engine.core.system.StandaloneSession;
import org.pentaho.platform.engine.core.system.boot.PlatformInitializationException;
import org.pentaho.platform.plugin.services.importer.NameBaseMimeResolver;
import org.pentaho.platform.repository2.ClientRepositoryPaths;
import org.pentaho.platform.repository2.mt.RepositoryTenantManager;
import org.pentaho.platform.repository2.unified.DefaultRepositoryVersionManager;
import org.pentaho.platform.repository2.unified.IRepositoryFileDao;
import org.pentaho.platform.repository2.unified.ServerRepositoryPaths;
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.policy.rolebased.RoleAuthorizationPolicy;
import org.pentaho.platform.security.userroledao.service.UserRoleDaoUserDetailsService;
import org.pentaho.platform.security.userroledao.service.UserRoleDaoUserRoleListService;
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.authentication.UsernamePasswordAuthenticationToken;
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.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.ClientResponse.Status;
import com.sun.jersey.api.client.UniformInterfaceException;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.test.framework.AppDescriptor;
import com.sun.jersey.test.framework.JerseyTest;
import com.sun.jersey.test.framework.WebAppDescriptor;
import com.sun.jersey.test.framework.spi.container.TestContainerFactory;
import com.sun.jersey.test.framework.spi.container.grizzly.GrizzlyTestContainerFactory;
import com.sun.jersey.test.framework.spi.container.grizzly.web.GrizzlyWebTestContainerFactory;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/repository.spring.xml",
        "classpath:/repository-test-override.spring.xml" })
@SuppressWarnings("nls")
public class DirectoryResourceIT extends JerseyTest implements ApplicationContextAware {

    private static MicroPlatform mp = new MicroPlatform();

    private static WebAppDescriptor webAppDescriptor = new WebAppDescriptor.Builder(
            "org.pentaho.platform.web.http.api.resources").contextPath("api").build();

    public static final String MAIN_TENANT_1 = "maintenant1";

    private IUnifiedRepository repo;

    private IUserRoleListService userRoleListService;

    private boolean startupCalled;

    private String repositoryAdminUsername;

    private String adminAuthorityName;

    private String authenticatedAuthorityName;

    private JcrTemplate testJcrTemplate;

    private IBackingRepositoryLifecycleManager manager;

    private IAuthorizationPolicy authorizationPolicy;

    IUserRoleDao userRoleDao;

    private ITenantManager tenantManager;
    private String sysAdminAuthorityName;
    private String sysAdminUserName;
    private IRepositoryFileDao repositoryFileDao;
    private ITenantedPrincipleNameResolver tenantedRoleNameUtils;
    private ITenantedPrincipleNameResolver tenantedUserNameUtils;
    private IRoleAuthorizationPolicyRoleBindingDao roleBindingDaoTarget;
    public static final String SYSTEM_PROPERTY = "spring.security.strategy";

    public DirectoryResourceIT() throws Exception {
        super();
        this.setTestContainerFactory(new GrizzlyTestContainerFactory());
        mp.setFullyQualifiedServerUrl(getBaseURI() + webAppDescriptor.getContextPath() + "/");
    }

    protected AppDescriptor configure() {
        return webAppDescriptor;
    }

    protected TestContainerFactory getTestContainerFactory() {
        return new GrizzlyWebTestContainerFactory();
    }

    @BeforeClass
    public static void beforeClass() throws Exception {
        System.setProperty(SYSTEM_PROPERTY, "MODE_GLOBAL");
        PentahoSessionHolder.setStrategyName(PentahoSessionHolder.MODE_GLOBAL);

        FileUtils.deleteDirectory(new File("/tmp/jackrabbit-test-TRUNK"));
        SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_GLOBAL);
    }

    @AfterClass
    public static void afterClass() {
        PentahoSessionHolder.setStrategyName(PentahoSessionHolder.MODE_GLOBAL);
        SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_GLOBAL);
    }

    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);
        }
    }

    @Before
    public void beforeTest() throws PlatformInitializationException {
        mp = new MicroPlatform();
        // used by DefaultPentahoJackrabbitAccessControlHelper
        mp.defineInstance(IAuthorizationPolicy.class, authorizationPolicy);
        mp.defineInstance(ITenantManager.class, tenantManager);
        mp.define(ITenant.class, Tenant.class);
        mp.defineInstance("roleAuthorizationPolicyRoleBindingDaoTarget", roleBindingDaoTarget);
        mp.defineInstance(IRoleAuthorizationPolicyRoleBindingDao.class, roleBindingDaoTarget);
        mp.defineInstance("tenantedUserNameUtils", tenantedUserNameUtils);
        mp.defineInstance("tenantedRoleNameUtils", tenantedRoleNameUtils);
        mp.defineInstance("repositoryAdminUsername", repositoryAdminUsername);
        mp.define(IRoleAuthorizationPolicyRoleBindingDao.class, RoleAuthorizationPolicy.class, Scope.GLOBAL);
        mp.define(ITenantManager.class, RepositoryTenantManager.class, Scope.GLOBAL);
        mp.defineInstance("singleTenantAdminAuthorityName", new String("Administrator"));
        mp.defineInstance("RepositoryFileProxyFactory",
                new RepositoryFileProxyFactory(this.testJcrTemplate, this.repositoryFileDao));

        DefaultRepositoryVersionManager defaultRepositoryVersionManager = new DefaultRepositoryVersionManager();
        defaultRepositoryVersionManager.setPlatformMimeResolver(new NameBaseMimeResolver());
        mp.defineInstance(IRepositoryVersionManager.class, defaultRepositoryVersionManager);
        UserRoleDaoUserDetailsService userDetailsService = new UserRoleDaoUserDetailsService();
        userDetailsService.setUserRoleDao(userRoleDao);
        List<String> systemRoles = new ArrayList<String>();
        systemRoles.add("Admin");
        List<String> extraRoles = Arrays.asList(new String[] { "Authenticated", "Anonymous" });
        String adminRole = "Admin";

        userRoleListService = new UserRoleDaoUserRoleListService(userRoleDao, userDetailsService,
                tenantedUserNameUtils, systemRoles, extraRoles, adminRole);
        ((UserRoleDaoUserRoleListService) userRoleListService).setUserRoleDao(userRoleDao);
        ((UserRoleDaoUserRoleListService) userRoleListService).setUserDetailsService(userDetailsService);

        mp.defineInstance(IUserRoleListService.class, userRoleListService);
        mp.start();
        logout();
        startupCalled = true;
        SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_GLOBAL);
    }

    @After
    public void afterTest() throws Exception {
        clearRoleBindings();
        // null out fields to get back memory
        authorizationPolicy = null;
        loginAsRepositoryAdmin();
        SimpleJcrTestUtils.deleteItem(testJcrTemplate, ServerRepositoryPaths.getPentahoRootFolderPath());
        logout();
        repositoryAdminUsername = null;
        adminAuthorityName = null;
        authenticatedAuthorityName = null;
        authorizationPolicy = null;
        testJcrTemplate = null;
        if (startupCalled) {
            manager.shutdown();
        }
        mp.stop();
        // null out fields to get back memory
        repo = null;
    }

    protected void clearRoleBindings() throws Exception {
        loginAsRepositoryAdmin();
    }

    protected void createTestFile(String pathId, String text) {
        WebResource webResource = resource();
        ClientResponse response = webResource.path("repo/files/" + pathId).type(TEXT_PLAIN)
                .put(ClientResponse.class, text);
        assertResponse(response, Status.OK);
    }

    protected void createTestFileBinary(String pathId, byte[] data) {
        WebResource webResource = resource();
        ClientResponse response = webResource.path("repo/files/" + pathId).type(APPLICATION_OCTET_STREAM)
                .put(ClientResponse.class, new String(data));
        assertResponse(response, Status.OK);
    }

    protected void createTestFolder(String pathId) {
        WebResource webResource = resource();
        // webResource.path("repo/dirs/" + pathId).put();
        ClientResponse response = webResource.path("repo/dirs/" + pathId).type(TEXT_PLAIN)
                .put(ClientResponse.class);
        assertResponse(response, Status.OK);
    }

    public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
        manager = (IBackingRepositoryLifecycleManager) applicationContext
                .getBean("backingRepositoryLifecycleManager");
        SessionFactory jcrSessionFactory = (SessionFactory) applicationContext.getBean("jcrSessionFactory");
        testJcrTemplate = new JcrTemplate(jcrSessionFactory);
        testJcrTemplate.setAllowCreate(true);
        testJcrTemplate.setExposeNativeSession(true);
        repositoryAdminUsername = (String) applicationContext.getBean("repositoryAdminUsername");
        authenticatedAuthorityName = (String) applicationContext.getBean("singleTenantAuthenticatedAuthorityName");
        adminAuthorityName = (String) applicationContext.getBean("singleTenantAdminAuthorityName");
        sysAdminAuthorityName = (String) applicationContext.getBean("superAdminAuthorityName");
        sysAdminUserName = (String) applicationContext.getBean("superAdminUserName");
        authorizationPolicy = (IAuthorizationPolicy) applicationContext.getBean("authorizationPolicy");
        roleBindingDaoTarget = (IRoleAuthorizationPolicyRoleBindingDao) applicationContext
                .getBean("roleAuthorizationPolicyRoleBindingDaoTarget");
        tenantManager = (ITenantManager) applicationContext.getBean("tenantMgrTxn");
        repositoryFileDao = (IRepositoryFileDao) applicationContext.getBean("repositoryFileDao");
        userRoleDao = (IUserRoleDao) applicationContext.getBean("userRoleDaoTxn");
        tenantedUserNameUtils = (ITenantedPrincipleNameResolver) applicationContext
                .getBean("tenantedUserNameUtils");
        tenantedRoleNameUtils = (ITenantedPrincipleNameResolver) applicationContext
                .getBean("tenantedRoleNameUtils");
        repo = (IUnifiedRepository) applicationContext.getBean("unifiedRepository");
        TestPrincipalProvider.userRoleDao = (IUserRoleDao) applicationContext.getBean("userRoleDaoTxn");
        TestPrincipalProvider.adminCredentialsStrategy = (CredentialsStrategy) applicationContext
                .getBean("jcrAdminCredentialsStrategy");
        TestPrincipalProvider.repository = (Repository) applicationContext.getBean("jcrRepository");
    }

    protected void loginAsRepositoryAdmin() {
        StandaloneSession pentahoSession = new StandaloneSession(repositoryAdminUsername);
        pentahoSession.setAuthenticated(repositoryAdminUsername);
        final List<GrantedAuthority> repositoryAdminAuthorities = Arrays
                .asList(new GrantedAuthority[] { new SimpleGrantedAuthority(sysAdminAuthorityName) });
        final String password = "ignored";
        UserDetails repositoryAdminUserDetails = new User(repositoryAdminUsername, password, true, true, true, true,
                repositoryAdminAuthorities);
        Authentication repositoryAdminAuthentication = new UsernamePasswordAuthenticationToken(
                repositoryAdminUserDetails, password, repositoryAdminAuthorities);
        PentahoSessionHolder.setSession(pentahoSession);
        // this line necessary for Spring Security's MethodSecurityInterceptor
        SecurityContextHolder.getContext().setAuthentication(repositoryAdminAuthentication);
    }

    protected void logout() {
        PentahoSessionHolder.removeSession();
        SecurityContextHolder.getContext().setAuthentication(null);
    }

    protected void login(final String username, final ITenant tenant) {
        login(username, tenant, false);
    }

    /**
     * Logs in with given username.
     *
     * @param username username of user
     * @param tenant   tenant to which this user belongs
     * @tenantAdmin true to add the tenant admin authority to the user's roles
     */
    protected void login(final String username, final ITenant tenant, String[] roles) {
        StandaloneSession pentahoSession = new StandaloneSession(username);
        pentahoSession.setAuthenticated(tenant.getId(), username);
        PentahoSessionHolder.setSession(pentahoSession);
        pentahoSession.setAttribute(IPentahoSession.TENANT_ID_KEY, tenant.getId());
        final String password = "password";

        List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>();

        for (String roleName : roles) {
            authList.add(new SimpleGrantedAuthority(roleName));
        }
        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);
    }

    /**
     * Logs in with given username.
     *
     * @param username username of user
     * @param tenant   tenant to which this user belongs
     * @tenantAdmin true to add the tenant admin authority to the user's roles
     */
    protected void login(final String username, final ITenant tenant, final boolean tenantAdmin) {
        StandaloneSession pentahoSession = new StandaloneSession(username);
        pentahoSession.setAuthenticated(username);
        pentahoSession.setAttribute(IPentahoSession.TENANT_ID_KEY, tenant.getId());
        final String password = "password";

        List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>();
        authList.add(new SimpleGrantedAuthority(authenticatedAuthorityName));
        if (tenantAdmin) {
            authList.add(new SimpleGrantedAuthority(adminAuthorityName));
        }
        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);
    }

    @Test
    public void testCreateDir() {
        loginAsRepositoryAdmin();
        ITenant systemTenant = tenantManager.createTenant(null, ServerRepositoryPaths.getPentahoRootFolderName(),
                adminAuthorityName, authenticatedAuthorityName, "Anonymous");
        userRoleDao.createUser(systemTenant, sysAdminUserName, "password", "", new String[] { adminAuthorityName });
        ITenant mainTenant_1 = tenantManager.createTenant(systemTenant, MAIN_TENANT_1, adminAuthorityName,
                authenticatedAuthorityName, "Anonymous");
        userRoleDao.createUser(mainTenant_1, "admin", "password", "", new String[] { adminAuthorityName });
        try {
            login("admin", mainTenant_1, new String[] { authenticatedAuthorityName });

            // set object in PentahoSystem
            mp.defineInstance(IUnifiedRepository.class, repo);

            WebResource webResource = resource();
            String publicFolderPath = ClientRepositoryPaths.getPublicFolderPath();
            String newDirPathId = publicFolderPath.replaceAll("/", ":") + ":testDir";

            // Create directory. Success is expected.
            webResource.path("repo/dirs/" + newDirPathId).put();

            // Create duplicate directory. CONFLICT (409) is expected.
            try {
                webResource.path("repo/dirs/" + newDirPathId).put();
                fail("CONFLICT is expected");
            } catch (UniformInterfaceException e) {
                assertEquals(Response.Status.CONFLICT.getStatusCode(), e.getResponse().getStatus());
            }
        } catch (AssertionError assertion) {
            throw assertion;
        } catch (Throwable ex) {
            TestCase.fail(ex.getMessage());
        } finally {
            cleanupUserAndRoles(mainTenant_1);
            cleanupUserAndRoles(systemTenant);
            logout();
        }
    }

    @Test
    public void testCreateDir_RootLevel() {
        loginAsRepositoryAdmin();
        ITenant systemTenant = tenantManager.createTenant(null, ServerRepositoryPaths.getPentahoRootFolderName(),
                adminAuthorityName, authenticatedAuthorityName, "Anonymous");
        userRoleDao.createUser(systemTenant, sysAdminUserName, "password", "", new String[] { adminAuthorityName });
        ITenant mainTenant_1 = tenantManager.createTenant(systemTenant, MAIN_TENANT_1, adminAuthorityName,
                authenticatedAuthorityName, "Anonymous");
        userRoleDao.createUser(mainTenant_1, "admin", "password", "", new String[] { adminAuthorityName });
        try {
            login("admin", mainTenant_1, new String[] { authenticatedAuthorityName });

            // set object in PentahoSystem
            mp.defineInstance(IUnifiedRepository.class, repo);

            WebResource webResource = resource();
            String rootLevelDirPathId = ":testRootLevelDir";

            // Create duplicate directory. FORBIDDEN (403) is expected.
            try {
                webResource.path("repo/dirs/" + rootLevelDirPathId).put();
                fail("FORBIDDEN is expected");
            } catch (UniformInterfaceException e) {
                assertEquals(Response.Status.FORBIDDEN.getStatusCode(), e.getResponse().getStatus());
            }
        } catch (AssertionError assertion) {
            throw assertion;
        } catch (Throwable ex) {
            TestCase.fail(ex.getMessage());
        } finally {
            cleanupUserAndRoles(mainTenant_1);
            cleanupUserAndRoles(systemTenant);
            logout();
        }
    }

    @Test
    public void testCreateDir_ServerError() {
        loginAsRepositoryAdmin();
        ITenant systemTenant = tenantManager.createTenant(null, ServerRepositoryPaths.getPentahoRootFolderName(),
                adminAuthorityName, authenticatedAuthorityName, "Anonymous");
        userRoleDao.createUser(systemTenant, sysAdminUserName, "password", "", new String[] { adminAuthorityName });
        ITenant mainTenant_1 = tenantManager.createTenant(systemTenant, MAIN_TENANT_1, adminAuthorityName,
                authenticatedAuthorityName, "Anonymous");
        userRoleDao.createUser(mainTenant_1, "admin", "password", "", new String[] { adminAuthorityName });
        try {
            login("admin", mainTenant_1, new String[] { authenticatedAuthorityName });

            // set object in PentahoSystem
            mp.defineInstance(IUnifiedRepository.class, repo);

            WebResource webResource = resource();
            String invalidPathId = "/////";

            // Invalid path id. INTERNAL_SERVER_ERROR (500) is expected.
            try {
                webResource.path("repo/dirs/" + invalidPathId).put();
                fail("INTERNAL_SERVER_ERROR is expected");
            } catch (UniformInterfaceException e) {
                assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e.getResponse().getStatus());
            }
        } catch (AssertionError assertion) {
            throw assertion;
        } catch (Throwable ex) {
            TestCase.fail(ex.getMessage());
        } finally {
            cleanupUserAndRoles(mainTenant_1);
            cleanupUserAndRoles(systemTenant);
            logout();
        }
    }
}