001/**
002 * Copyright 2005-2016 The Kuali Foundation
003 *
004 * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
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.kuali.rice.kew.impl.document.security;
017
018import org.apache.commons.lang.StringUtils;
019import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
020import org.kuali.rice.kew.api.document.Document;
021import org.kuali.rice.kew.api.extension.ExtensionDefinition;
022import org.kuali.rice.kew.api.extension.ExtensionRepositoryService;
023import org.kuali.rice.kew.api.extension.ExtensionUtils;
024import org.kuali.rice.kew.framework.document.security.DocumentSecurityDirective;
025import org.kuali.rice.kew.framework.document.security.DocumentSecurityHandlerService;
026import org.kuali.rice.kew.framework.document.security.DocumentSecurityAttribute;
027
028import java.util.ArrayList;
029import java.util.Collections;
030import java.util.HashMap;
031import java.util.List;
032import java.util.Map;
033
034/**
035 * Reference implementation of the DocumentSecurityHandlerService.
036 *
037 * @author Kuali Rice Team (rice.collab@kuali.org)
038 */
039public class DocumentSecurityHandlerServiceImpl implements DocumentSecurityHandlerService {
040
041    private ExtensionRepositoryService extensionRepositoryService;
042
043    @Override
044    public List<String> getAuthorizedDocumentIds(String principalId, List<DocumentSecurityDirective> documentSecurityDirectives ) {
045        if (StringUtils.isBlank(principalId)) {
046            throw new RiceIllegalArgumentException("principalId was null or blank");
047        }
048        if (documentSecurityDirectives == null) {
049            documentSecurityDirectives = Collections.emptyList();
050        }
051        List<String> authorizedDocumentIds = new ArrayList<String>();
052        Map<String, DocumentSecurityAttribute> securityAttributeCache = new HashMap<String, DocumentSecurityAttribute>();
053        for (DocumentSecurityDirective documentSecurityDirective : documentSecurityDirectives) {
054            List<DocumentSecurityAttribute> attributesToApply = loadSecurityAttributes(documentSecurityDirective, securityAttributeCache);
055            for (Document document : documentSecurityDirective.getDocuments()) {
056                // if it's already authorized, we don't need to do anything
057                if (!authorizedDocumentIds.contains(document.getDocumentId())) {
058                    for (DocumentSecurityAttribute securityAttribute : attributesToApply) {
059                        if (securityAttribute.isAuthorizedForDocument(principalId, document)) {
060                            authorizedDocumentIds.add(document.getDocumentId());
061                            break;
062                        }
063                    }
064                }
065            }
066        }
067        return authorizedDocumentIds;
068    }
069
070    protected List<DocumentSecurityAttribute> loadSecurityAttributes(DocumentSecurityDirective documentSecurityDirective,
071            Map<String, DocumentSecurityAttribute> securityAttributeCache) {
072        List<DocumentSecurityAttribute> securityAttributes = new ArrayList<DocumentSecurityAttribute>();
073        for (String documentSecurityAttributeName : documentSecurityDirective.getDocumentSecurityAttributeNames()) {
074            securityAttributes.add(loadAndCacheSecurityAttribute(documentSecurityAttributeName, securityAttributeCache));
075        }
076        return securityAttributes;
077    }
078
079    protected DocumentSecurityAttribute loadAndCacheSecurityAttribute(String securityAttributeName, Map<String, DocumentSecurityAttribute> securityAttributeCache) {
080        if (securityAttributeCache.containsKey(securityAttributeName)) {
081            return securityAttributeCache.get(securityAttributeName);
082        }
083        ExtensionDefinition extensionDefinition = extensionRepositoryService.getExtensionByName(securityAttributeName);
084        if (extensionDefinition == null) {
085            throw new RiceIllegalArgumentException("Failed to locate a SecurityAttribute with the given name: " + securityAttributeName);
086        }
087        DocumentSecurityAttribute securityAttribute = loadSecurityAttribute(extensionDefinition);
088        securityAttributeCache.put(securityAttributeName, securityAttribute);
089        return securityAttribute;
090    }
091
092    protected DocumentSecurityAttribute loadSecurityAttribute(ExtensionDefinition extensionDefinition) {
093        Object securityAttribute = ExtensionUtils.loadExtension(extensionDefinition);
094        if (securityAttribute == null) {
095            throw new RiceIllegalArgumentException("Failed to load SecurityAttribute for: " + extensionDefinition);
096        }
097        return (DocumentSecurityAttribute)securityAttribute;
098    }
099
100    public ExtensionRepositoryService getExtensionRepositoryService() {
101        return extensionRepositoryService;
102    }
103
104    public void setExtensionRepositoryService(ExtensionRepositoryService extensionRepositoryService) {
105        this.extensionRepositoryService = extensionRepositoryService;
106    }
107
108}