001/*
002 * Licensed to DuraSpace under one or more contributor license agreements.
003 * See the NOTICE file distributed with this work for additional information
004 * regarding copyright ownership.
005 *
006 * DuraSpace licenses this file to you under the Apache License,
007 * Version 2.0 (the "License"); you may not use this file except in
008 * compliance with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.fcrepo.auth.integration;
019
020import static org.junit.Assert.assertEquals;
021import static org.mockito.Matchers.any;
022import static org.mockito.Matchers.eq;
023import static org.mockito.Mockito.atLeastOnce;
024import static org.mockito.Mockito.mock;
025import static org.mockito.Mockito.verify;
026import static org.mockito.Mockito.when;
027import static org.slf4j.LoggerFactory.getLogger;
028
029import java.security.Principal;
030
031import javax.inject.Inject;
032import javax.jcr.AccessDeniedException;
033import javax.jcr.Repository;
034import javax.jcr.RepositoryException;
035import javax.jcr.Session;
036import javax.servlet.http.HttpServletRequest;
037
038import org.apache.http.auth.BasicUserPrincipal;
039import org.fcrepo.auth.common.FedoraAuthorizationDelegate;
040import org.fcrepo.auth.common.ServletContainerAuthenticationProvider;
041import org.fcrepo.kernel.api.exception.RepositoryRuntimeException;
042import org.fcrepo.kernel.api.services.ContainerService;
043import org.fcrepo.kernel.modeshape.services.ContainerServiceImpl;
044import org.junit.Assert;
045import org.junit.Test;
046import org.junit.runner.RunWith;
047import org.mockito.Mockito;
048import org.modeshape.jcr.api.ServletCredentials;
049import org.modeshape.jcr.value.Path;
050import org.slf4j.Logger;
051import org.springframework.test.context.ContextConfiguration;
052import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
053
054/**
055 * @author Peter Eichman
056 */
057@RunWith(SpringJUnit4ClassRunner.class)
058@ContextConfiguration(locations = { "/spring-test/mocked-fad-repo-3.xml" })
059public class DelegatedUserIT {
060
061    private static Logger logger =
062            getLogger(DelegatedUserIT.class);
063
064    @Inject
065    private Repository repo;
066
067    @Inject
068    private FedoraAuthorizationDelegate fad;
069
070    private final HttpServletRequest request = mock(HttpServletRequest.class);
071
072    @Test
073    public void testFactory() {
074        Assert.assertNotNull(
075                "AuthenticationProvider must return a AuthenticationProvider",
076                ServletContainerAuthenticationProvider.getInstance());
077    }
078
079    @Test
080    public void testDelegatedUserAccess() throws RepositoryException {
081
082        // mock request by an admin user, on behalf of a regular user
083        when(request.getRemoteUser()).thenReturn("admin1");
084        when(request.getUserPrincipal()).thenReturn(new BasicUserPrincipal("admin1"));
085        when(request.isUserInRole(eq(ServletContainerAuthenticationProvider.FEDORA_ADMIN_ROLE))).thenReturn(true);
086        when(request.getHeader("On-Behalf-Of")).thenReturn("user1");
087
088        Mockito.reset(fad);
089        // set up a restrictive mock FAD, which should deny non-admin users
090        when(fad.hasPermission(any(Session.class), any(Path.class), any(String[].class))).thenReturn(false);
091
092        final ServletCredentials credentials = new ServletCredentials(request);
093        final Session session = repo.login(credentials);
094        assertEquals("Session user principal is user1",
095                "user1",
096                ((Principal) session.getAttribute(FedoraAuthorizationDelegate.FEDORA_USER_PRINCIPAL)).getName());
097
098        // try to create an object, this should fail because it is being executed as a non-admin user
099        final ContainerService os = new ContainerServiceImpl();
100        try {
101            os.findOrCreate(session, "/myobject");
102        } catch (final RepositoryRuntimeException e) {
103            final Throwable cause = e.getCause();
104            if (cause != null && cause instanceof AccessDeniedException) {
105                logger.debug("caught expected access denied exception");
106            } else {
107                throw e;
108            }
109        }
110        verify(fad, atLeastOnce()).hasPermission(any(Session.class), any(Path.class), any(String[].class));
111    }
112
113}