/** * Copyright 2008 The University of North Carolina at Chapel Hill * * 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 edu.unc.lib.dl.ui.util; import java.util.HashMap; import java.util.Map; import java.util.WeakHashMap; import java.util.concurrent.atomic.AtomicLong; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import edu.unc.lib.dl.acl.service.AccessControlService; import edu.unc.lib.dl.acl.util.AccessGroupConstants; import edu.unc.lib.dl.acl.util.AccessGroupSet; import edu.unc.lib.dl.acl.util.ObjectAccessControlsBean; import edu.unc.lib.dl.acl.util.Permission; import edu.unc.lib.dl.fedora.InvalidDatastreamException; import edu.unc.lib.dl.fedora.PID; import edu.unc.lib.dl.search.solr.model.SimpleIdRequest; import edu.unc.lib.dl.ui.service.SolrQueryLayerService; import edu.unc.lib.dl.util.ContentModelHelper.Datastream; /** * Utility for determining if a particular user has access to an object or datastream. * * @author bbpennel */ public class UserAccessUtil { private static final Logger LOG = LoggerFactory.getLogger(UserAccessUtil.class); private Permission defaultPermission = Permission.viewDescription; private AccessControlService accessControlService; // Temporarily using this to check publication status private SolrQueryLayerService solrQueryLayer; // Cache of answers as to whether or not a user has access to a particular object or object's datastream // <PID, <group, Answer>> private WeakHashMap<String, Map<String, Boolean>> pids2User2Access = new WeakHashMap<String, Map<String, Boolean>>( 256); private AtomicLong lastCleared = new AtomicLong(0); // Time interval between cache clears private long clearInterval = 1000 * 60 * 2; public boolean hasAccess(String id, String user, AccessGroupSet groups) { clearCacheOnInterval(); // Check for cached version Map<String, Boolean> user2Access = this.pids2User2Access.get(id); if (user2Access != null) { Boolean answer = user2Access.get(user); if (answer != null) { LOG.debug("Answering user " + user + " from cache for " + id + " with answer " + answer); return answer; } } PID pid = new PID(id); boolean answer; if (groups.contains(AccessGroupConstants.ADMIN_GROUP)){ answer = true; } else { // Determine what permission we are looking for String[] idParts = pid.getPid().split("/"); Permission permission = null; Datastream datastream = null; if (idParts.length > 1) { id = idParts[0]; datastream = Datastream.getDatastream(idParts[1]); if (datastream == null) { throw new InvalidDatastreamException(idParts[1] + " is not a valid datastream identifer"); } permission = Permission.getPermissionByDatastreamCategory(datastream.getCategory()); } else { permission = defaultPermission; } // Check if the item is accessible to the user according to publish status SimpleIdRequest isPublishedRequest = new SimpleIdRequest(id, groups); boolean isPublished = solrQueryLayer.isAccessible(isPublishedRequest); // Get access info from Fedora if user is not blocked by publication rights and this is a datastream request if (isPublished && datastream != null) { ObjectAccessControlsBean aclBean = accessControlService.getObjectAccessControls(new PID(id)); answer = aclBean.hasPermission(groups, permission); } else { answer = isPublished; } } if (user2Access == null) { user2Access = new HashMap<String, Boolean>(); this.pids2User2Access.put(pid.getPid(), user2Access); } user2Access.put(user, answer); LOG.debug("Answering user " + user + " for " + id + " with answer " + answer + ", storing to cache"); return answer; } private void clearCacheOnInterval() { synchronized(lastCleared) { long currentTime = System.currentTimeMillis(); if (currentTime - lastCleared.get() > clearInterval) { if (this.pids2User2Access.size() > 0) this.pids2User2Access.clear(); lastCleared.set(currentTime); } } } public void updateAccess(String pid, String user, AccessGroupSet groups) { this.pids2User2Access.remove(pid); this.hasAccess(pid, user, groups); } public void clear() { synchronized(lastCleared) { this.pids2User2Access.clear(); lastCleared.set(System.currentTimeMillis()); } } public void setDefaultPermission(Permission defaultPermission) { this.defaultPermission = defaultPermission; } public void setAccessControlService(AccessControlService accessControlService) { this.accessControlService = accessControlService; } public void setSolrQueryLayer(SolrQueryLayerService solrQueryLayer) { this.solrQueryLayer = solrQueryLayer; } }