001/**
002 * Copyright 2015 DuraSpace, Inc.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.fcrepo.auth.common;
017
018import static java.util.Collections.emptySet;
019
020import java.security.Principal;
021import java.util.HashSet;
022import java.util.Iterator;
023import java.util.Set;
024
025import javax.jcr.Credentials;
026import javax.servlet.http.HttpServletRequest;
027
028import org.modeshape.jcr.api.ServletCredentials;
029import org.slf4j.Logger;
030import org.slf4j.LoggerFactory;
031
032/**
033 * Adds principals based on roles that are configured within the container and
034 * through a PrincipalProvider bean in the project.
035 *
036 * @author Kevin S. Clarke
037 * @see PrincipalProvider
038 */
039public class ContainerRolesPrincipalProvider implements PrincipalProvider {
040
041    private static final Logger LOGGER = LoggerFactory.getLogger(ContainerRolesPrincipalProvider.class);
042
043    protected static class ContainerRolesPrincipal implements Principal {
044
045        private final String name;
046
047        ContainerRolesPrincipal(final String name) {
048            this.name = name;
049        }
050
051        @Override
052        public String getName() {
053            return name;
054        }
055
056        @Override
057        public String toString() {
058            return name;
059        }
060
061        @Override
062        public boolean equals(final Object o) {
063            if (o instanceof ContainerRolesPrincipal) {
064                return ((ContainerRolesPrincipal) o).getName().equals(this.getName());
065            }
066
067            return false;
068        }
069
070        @Override
071        public int hashCode() {
072            if (name == null) {
073                return 0;
074            }
075
076            return name.hashCode();
077        }
078
079    }
080
081    private Set<String> roleNames;
082
083    /**
084     * Sets the role names which have been configured in the repo.xml file.
085     *
086     * @param roleNames The names of container roles that should be recognized
087     *        as principals
088     */
089    public void setRoleNames(final Set<String> roleNames) {
090        this.roleNames = roleNames;
091    }
092
093    /*
094     * (non-Javadoc)
095     * @see
096     * org.fcrepo.auth.PrincipalProvider#getPrincipals(javax.jcr.Credentials)
097     */
098    @Override
099    public Set<Principal> getPrincipals(final Credentials credentials) {
100        LOGGER.debug("Checking for principals using {}", ContainerRolesPrincipalProvider.class.getSimpleName());
101
102        if (!(credentials instanceof ServletCredentials)) {
103            LOGGER.debug("Credentials is not an instanceof ServletCredentials");
104
105            return emptySet();
106        }
107
108        final ServletCredentials servletCredentials = (ServletCredentials) credentials;
109        final HttpServletRequest request = servletCredentials.getRequest();
110
111        if (request == null) {
112            LOGGER.debug("Servlet request from servletCredentials was null");
113
114            return emptySet();
115        }
116
117        if (roleNames == null) {
118            LOGGER.debug("Role names Set was never initialized");
119
120            return emptySet();
121        }
122
123        final Iterator<String> iterator = roleNames.iterator();
124        final Set<Principal> principals = new HashSet<>();
125
126        while (iterator.hasNext()) {
127            final String role = iterator.next().trim();
128
129            if (request.isUserInRole(role)) {
130                LOGGER.debug("Adding container role as principal: {}", role);
131
132                principals.add(new ContainerRolesPrincipal(role));
133            }
134        }
135
136        return principals;
137    }
138
139}