org.fcrepo.auth.roles.basic.integration.AbstractBasicRolesIT.java Source code

Java tutorial

Introduction

Here is the source code for org.fcrepo.auth.roles.basic.integration.AbstractBasicRolesIT.java

Source

/**
 * Copyright 2013 DuraSpace, Inc.
 *
 * 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.fcrepo.auth.roles.basic.integration;

import static javax.ws.rs.core.Response.Status.CREATED;
import static org.fcrepo.auth.ServletContainerAuthenticationProvider.EVERYONE_NAME;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.slf4j.LoggerFactory.getLogger;

import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.message.AbstractHttpMessage;
import org.apache.http.util.EntityUtils;
import org.codehaus.jackson.map.ObjectMapper;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/spring-test/test-container.xml")
public abstract class AbstractBasicRolesIT {

    private static Logger logger = getLogger(AbstractBasicRolesIT.class);

    protected static final int SERVER_PORT = Integer.parseInt(System.getProperty("test.port", "8080"));

    protected static final String HOSTNAME = "localhost";

    protected static final String SUFFIX = "fcr:accessRoles";

    protected static final String serverAddress = "http://" + HOSTNAME + ":" + SERVER_PORT + "/rest/";

    protected final PoolingClientConnectionManager connectionManager = new PoolingClientConnectionManager();

    protected static HttpClient client;

    private final static List<BasicRolesPepTestObjectBean> test_objs = defineTestObjects();

    private static boolean is_setup = false;

    public AbstractBasicRolesIT() {
        connectionManager.setMaxTotal(Integer.MAX_VALUE);
        connectionManager.setDefaultMaxPerRoute(20);
        connectionManager.closeIdleConnections(3, TimeUnit.SECONDS);
        client = new DefaultHttpClient(connectionManager);
    }

    @Before
    public void setUp() throws Exception {
        if (is_setup == false) {
            for (final BasicRolesPepTestObjectBean obj : test_objs) {

                deleteTestObject(obj);
                ingestObject(obj);
            }
            is_setup = true;
            logger.info("SETUP SUCCESSFUL");
        }
    }

    protected HttpGet getRolesMethod(final String param) {
        final HttpGet get = new HttpGet(serverAddress + param + "/" + SUFFIX);
        logger.debug("GET: {}", get.getURI());
        return get;
    }

    protected HttpGet getEffectiveRolesMethod(final String param) {
        final HttpGet get = new HttpGet(serverAddress + param + "/" + SUFFIX + "?effective");
        logger.debug("GET: {}", get.getURI());
        return get;
    }

    protected HttpGet getObjectMethod(final String param) {
        final HttpGet get = new HttpGet(serverAddress + param);
        logger.debug("GET: {}", get.getURI());
        return get;
    }

    protected HttpPost postObjMethod(final String param) {
        final HttpPost post = new HttpPost(serverAddress + param);
        logger.debug("POST: {}", post.getURI());
        return post;
    }

    protected HttpPut putDSMethod(final String objectPath, final String ds, final String content)
            throws UnsupportedEncodingException {
        final HttpPut put = new HttpPut(serverAddress + objectPath + "/" + ds + "/fcr:content");
        put.setEntity(new StringEntity(content));
        logger.debug("PUT: {}", put.getURI());
        return put;
    }

    protected HttpPost postDSMethod(final String objectPath, final String ds, final String content)
            throws UnsupportedEncodingException {
        final HttpPost post = new HttpPost(serverAddress + objectPath + "/" + ds + "/fcr:content");
        post.setEntity(new StringEntity(content));
        return post;
    }

    protected HttpPost postRolesMethod(final String param) {
        final HttpPost post = new HttpPost(serverAddress + param + "/" + SUFFIX);
        logger.debug("POST: {}", post.getURI());
        return post;
    }

    protected HttpDelete deleteObjMethod(final String param) {
        final HttpDelete delete = new HttpDelete(serverAddress + param);
        logger.debug("DELETE: {}", delete.getURI());
        return delete;
    }

    protected HttpDelete deleteRolesMethod(final String param) {
        final HttpDelete delete = new HttpDelete(serverAddress + param + "/" + SUFFIX);
        logger.debug("DELETE: {}", delete.getURI());
        return delete;
    }

    protected HttpResponse execute(final HttpUriRequest method) throws IOException {
        logger.debug("Executing: " + method.getMethod() + " to " + method.getURI());
        return client.execute(method);
    }

    protected int getStatus(final HttpUriRequest method) throws IOException {
        final HttpResponse response = execute(method);
        final int result = response.getStatusLine().getStatusCode();
        if (!(result > 199) || !(result < 400)) {
            logger.warn(EntityUtils.toString(response.getEntity()));
        }
        return result;
    }

    protected int canRead(final String username, final String path, final boolean is_authenticated)
            throws IOException {
        // get the object info
        final HttpGet method = getObjectMethod(path);
        if (is_authenticated) {
            setAuth(method, username);
        }
        final HttpResponse response = client.execute(method);
        final int status = response.getStatusLine().getStatusCode();
        logger.debug("canRead REST response status code [user: {}, path: {}]: {}", username, path, status);
        return status;
    }

    protected int canAddDS(final String username, final String path, final String dsName,
            final boolean is_authenticated) throws IOException {
        final HttpPost method = postDSMethod(path, dsName, "This is the datastream contents.");
        if (is_authenticated) {
            setAuth(method, username);
        }
        final HttpResponse response = client.execute(method);
        final int status = response.getStatusLine().getStatusCode();
        logger.debug("canAddDS REST response status code:  {}", status);
        return status;
    }

    protected int canUpdateDS(final String username, final String path, final String dsName,
            final boolean is_authenticated) throws IOException {
        final HttpPut method = putDSMethod(path, dsName, "This is my updated content.");
        if (is_authenticated) {
            setAuth(method, username);
        }
        final HttpResponse response = client.execute(method);
        final int status = response.getStatusLine().getStatusCode();
        logger.debug("canUpdateDS REST response status code:  {}", status);
        return status;
    }

    protected int canAddACL(final String username, final String path, final String principal, final String role,
            final boolean is_authenticated) throws IOException {
        final Map<String, String> tmap = new HashMap<String, String>();
        tmap.put(principal, role);
        final List<Map<String, String>> acls = Collections.singletonList(tmap);
        final String jsonACLs = createJsonACLs(acls);
        final HttpPost method = postRolesMethod(path);
        if (is_authenticated) {
            setAuth(method, username);
        }
        method.addHeader("Content-Type", "application/json");
        final StringEntity entity = new StringEntity(jsonACLs, "utf-8");
        method.setEntity(entity);
        final HttpResponse response = client.execute(method);
        final int status = response.getStatusLine().getStatusCode();
        logger.debug("canAddACL REST response status code:  {}", status);
        return status;
    }

    private void setAuth(final AbstractHttpMessage method, final String username) {
        final String creds = username + ":password";
        // in test configuration we don't need real passwords
        final String encCreds = new String(Base64.encodeBase64(creds.getBytes()));
        final String basic = "Basic " + encCreds;
        method.setHeader("Authorization", basic);
    }

    private void deleteTestObject(final BasicRolesPepTestObjectBean obj) {
        try {
            final HttpDelete method = deleteObjMethod(obj.getPath());
            setAuth(method, "fedoraAdmin");
            client.execute(method);
        } catch (final Throwable ignored) {
            logger.debug("object {} doesn't exist -- not deleting", obj.getPath());

        }
    }

    private void ingestObject(final BasicRolesPepTestObjectBean obj) throws Exception {
        final HttpPost method = postObjMethod(obj.getPath());
        setAuth(method, "fedoraAdmin");
        final HttpResponse response = client.execute(method);
        final String content = EntityUtils.toString(response.getEntity());
        final int status = response.getStatusLine().getStatusCode();
        assertEquals("Didn't get a CREATED response! Got content:\n" + content, CREATED.getStatusCode(), status);

        addObjectACLs(obj);
        addDatastreams(obj);
    }

    private void addObjectACLs(final BasicRolesPepTestObjectBean obj) throws Exception {
        if (obj.getACLs().size() > 0) {
            final String jsonACLs = createJsonACLs(obj.getACLs());

            final HttpPost method = postRolesMethod(obj.getPath());
            setAuth(method, "fedoraAdmin");
            method.addHeader("Content-Type", "application/json");
            final StringEntity entity = new StringEntity(jsonACLs, "utf-8");
            method.setEntity(entity);
            final HttpResponse response = client.execute(method);
            assertNotNull("There must be content for a post.", response.getEntity());
            final String content = EntityUtils.toString(response.getEntity());
            logger.debug("post response content: \n {}", content);
            assertEquals(CREATED.getStatusCode(), response.getStatusLine().getStatusCode());
        }
    }

    private void addDatastreams(final BasicRolesPepTestObjectBean obj) throws Exception {
        for (final Map<String, String> entries : obj.getDatastreams()) {
            for (final Map.Entry<String, String> entry : entries.entrySet()) {
                final String dsid = entry.getKey();
                final HttpPost method = postDSMethod(obj.getPath(), dsid, entry.getValue());
                setAuth(method, "fedoraAdmin");
                final HttpResponse response = client.execute(method);
                final String content = EntityUtils.toString(response.getEntity());
                final int status = response.getStatusLine().getStatusCode();
                assertEquals("Didn't get a CREATED response! Got content:\n" + content, CREATED.getStatusCode(),
                        status);
                addDatastreamACLs(obj, dsid);
            }
        }
    }

    private void addDatastreamACLs(final BasicRolesPepTestObjectBean obj, final String dsid) throws Exception {
        if (obj.getDatastreamACLs(dsid) != null) {
            final String jsonACLs = createJsonACLs(obj.getDatastreamACLs(dsid));
            logger.debug("addDatastreamACLs:  Datastream path: {}/{}", obj.getPath(), dsid);
            logger.debug("addDatastreamACLs:  JSON acls: {}{}", jsonACLs);
            final HttpPost method = postRolesMethod(obj.getPath() + "/" + dsid);
            setAuth(method, "fedoraAdmin");
            method.addHeader("Content-Type", "application/json");
            final StringEntity entity = new StringEntity(jsonACLs, "utf-8");
            method.setEntity(entity);
            final HttpResponse response = client.execute(method);
            assertEquals(CREATED.getStatusCode(), response.getStatusLine().getStatusCode());
        }
    }

    private String createJsonACLs(final List<Map<String, String>> principals_and_roles) {
        final Map<String, List<String>> acls = new HashMap<String, List<String>>();

        for (final Map<String, String> entries : principals_and_roles) {
            for (final Map.Entry<String, String> entry : entries.entrySet()) {
                acls.put(entry.getKey(), Collections.singletonList(entry.getValue()));
            }
        }
        return makeJson(acls);
    }

    private String makeJson(final Map<String, List<String>> roles) {
        final ObjectMapper mapper = new ObjectMapper();
        final StringWriter sw = new StringWriter();
        try {
            mapper.writeValue(sw, roles);
            return sw.toString();
        } catch (final IOException e) {
            throw new Error(e);
        }
    }

    private static List<BasicRolesPepTestObjectBean> defineTestObjects() {
        final List<BasicRolesPepTestObjectBean> test_objs = new ArrayList<BasicRolesPepTestObjectBean>();
        final BasicRolesPepTestObjectBean objA = new BasicRolesPepTestObjectBean();
        /* public object with public datastream */
        objA.setPath("testparent1");
        objA.addACL(EVERYONE_NAME, "reader");
        objA.addACL("examplereader", "reader");
        objA.addACL("examplewriter", "writer");
        objA.addACL("exampleadmin", "admin");
        objA.addDatastream("tsp1_data", "Test Parent 1, datastream 1,  Hello!");
        test_objs.add(objA);

        /* public object with one public datastream, one restricted datastream */
        final BasicRolesPepTestObjectBean objB = new BasicRolesPepTestObjectBean();
        objB.setPath("testparent2");
        objB.addACL(EVERYONE_NAME, "reader");
        objB.addACL("examplereader", "reader");
        objB.addACL("examplewriter", "writer");
        objB.addACL("exampleadmin", "admin");
        objB.addDatastream("tsp1_data", "Test Parent 2, datastream 1,  Hello!");
        objB.addDatastream("tsp2_data", "Test Parent 2, datastream 2,  secret stuff");
        objB.addDatastreamACL("tsp2_data", "examplereader", "reader");
        objB.addDatastreamACL("tsp2_data", "examplewriter", "writer");
        objB.addDatastreamACL("tsp2_data", "exampleadmin", "admin");
        test_objs.add(objB);

        /* public child object with datastream, no ACLs */
        final BasicRolesPepTestObjectBean objC = new BasicRolesPepTestObjectBean();
        objC.setPath("testparent1/testchild1NoACL");
        objC.addDatastream("tsc1_data", "Test Child 1, datastream 1,  Hello!");
        test_objs.add(objC);

        /* restricted child object with restricted datastreams */
        final BasicRolesPepTestObjectBean objD = new BasicRolesPepTestObjectBean();
        objD.setPath("testparent1/testchild2WithACL");
        objD.addACL("examplereader", "reader");
        objD.addACL("examplewriter", "writer");
        objD.addACL("exampleadmin", "admin");
        objD.addDatastream("tsc1_data", "Test Child 2, datastream 1,  really secret stuff");
        objD.addDatastream("tsc2_data", "Test Child 2, datastream 2,  really really secret stuff");
        objD.addDatastreamACL("tsc2_data", "examplewriter", "writer");
        objD.addDatastreamACL("tsc2_data", "exampleadmin", "admin");
        test_objs.add(objD);

        /*
         * even more restricted child object, with even more restricted
         * datastreams
         */
        final BasicRolesPepTestObjectBean objE = new BasicRolesPepTestObjectBean();
        objE.setPath("testparent1/testchild4WithACL");
        objE.addACL("examplewriter", "writer");
        objE.addACL("exampleadmin", "admin");
        objE.addDatastream("tsc1_data", "Test Child 3, datastream 1,  really secret stuff");
        objE.addDatastream("tsc2_data", "Test Child 3, datastream 2,  really really secret stuff");
        objE.addDatastreamACL("tsc2_data", "exampleadmin", "admin");
        test_objs.add(objE);

        /* private child object with 1 private datastream, 1 public datastream */
        final BasicRolesPepTestObjectBean objF = new BasicRolesPepTestObjectBean();
        objF.setPath("testparent2/testchild5WithACL");
        objF.addACL("exampleadmin", "admin");
        objF.addDatastream("tsc1_data", "Test Child 5, datastream 1, burn before reading");
        objF.addDatastream("tsc2_data", "Test Child 5, datastream 2, Hello!");
        objF.addDatastreamACL("tsc2_data", EVERYONE_NAME, "reader");
        test_objs.add(objF);

        return test_objs;

    }
}