mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged V3.1 to HEAD
12983: Merged V2.1-A to V3.1 8668: Added authorityDisplayName 12985: Merged V2.1-A to V3.1 8706: (record-only) Build fixes after removing the guest user - DO NOT MERGE 12990: Merged V3.0 to V3.1 12922: Merged V2.2 to V3.0 12555: Fix ETWOTWO-972 (Remove Lookup Cache) 12558: Fix ETWOTWO-978 (L2 Cache removal for No Row Issues) 12928: Merged V2.2 to V3.0 11319: Fix for ETWOTWO-73 (missed merge ?) ___________________________________________________________________ Modified: svn:mergeinfo Merged /alfresco/BRANCHES/V2.1-A:r8668,8706 Merged /alfresco/BRANCHES/V3.0:r12922,12928 Merged /alfresco/BRANCHES/V2.2:r12555,12558 Merged /alfresco/BRANCHES/V3.1:r12983,12985,12990 git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@13546 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -154,17 +154,7 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="lookupCache" class="org.alfresco.repo.avm.LookupCache">
|
||||
<property name="avmNodeDAO">
|
||||
<ref bean="avmNodeDAO"/>
|
||||
</property>
|
||||
<property name="avmStoreDAO">
|
||||
<ref bean="avmStoreDAO"/>
|
||||
</property>
|
||||
<property name="transactionalCache">
|
||||
<ref bean="avmLookupCache"/>
|
||||
</property>
|
||||
</bean>
|
||||
<bean id="lookupCache" class="org.alfresco.repo.avm.NOOPLookupCache"/>
|
||||
|
||||
<bean id="rawServices" class="org.alfresco.repo.avm.util.RawServices"/>
|
||||
|
||||
|
@@ -422,42 +422,6 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ===================================== -->
|
||||
<!-- AVM Lookup Cache -->
|
||||
<!-- ===================================== -->
|
||||
|
||||
<!-- The cross-transaction shared cache for AVM lookups -->
|
||||
|
||||
<bean name="avmLookupSharedCache" class="org.alfresco.repo.cache.EhCacheAdapter">
|
||||
<property name="cache">
|
||||
<bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
|
||||
<property name="cacheManager">
|
||||
<ref bean="internalEHCacheManager"/>
|
||||
</property>
|
||||
<property name="cacheName">
|
||||
<value>org.alfresco.repo.avm.lookupSharedCache</value>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Transactional cache for AVM lookups -->
|
||||
|
||||
<bean name="avmLookupCache" class="org.alfresco.repo.cache.TransactionalCache">
|
||||
<property name="sharedCache">
|
||||
<ref bean="avmLookupSharedCache"/>
|
||||
</property>
|
||||
<property name="cacheManager">
|
||||
<ref bean="transactionalEHCacheManager"/>
|
||||
</property>
|
||||
<property name="name">
|
||||
<value>org.alfresco.repo.avm.lookupTransactionalCache</value>
|
||||
</property>
|
||||
<property name="maxCacheSize">
|
||||
<value>100</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ===================================== -->
|
||||
<!-- AVM Store lookup cache -->
|
||||
<!-- ===================================== -->
|
||||
|
@@ -207,15 +207,17 @@
|
||||
eternal="true"
|
||||
overflowToDisk="false"
|
||||
/>
|
||||
<!-- Note: Workaround for ETWOTWO-978: no row issues - do not adjust -->
|
||||
<cache
|
||||
name="org.alfresco.repo.avm.VersionRootImpl"
|
||||
maxElementsInMemory="200"
|
||||
maxElementsInMemory="0"
|
||||
eternal="true"
|
||||
overflowToDisk="false"
|
||||
/>
|
||||
<!-- Note: Workaround for ETWOTWO-978: no row issues - do not adjust -->
|
||||
<cache
|
||||
name="org.alfresco.repo.avm.ChildEntryImpl"
|
||||
maxElementsInMemory="10000"
|
||||
maxElementsInMemory="0"
|
||||
eternal="true"
|
||||
overflowToDisk="false"
|
||||
/>
|
||||
|
@@ -0,0 +1,57 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
|
||||
|
||||
<!-- Activate this extension to enable AVM lookup path caching. -->
|
||||
<!-- This was the default behaviour prior to 2.2 SP3 & 3.1 -->
|
||||
|
||||
<beans>
|
||||
|
||||
<bean id="lookupCache" class="org.alfresco.repo.avm.TransactionalLookupCache">
|
||||
<property name="avmNodeDAO">
|
||||
<ref bean="avmNodeDAO"/>
|
||||
</property>
|
||||
<property name="avmStoreDAO">
|
||||
<ref bean="avmStoreDAO"/>
|
||||
</property>
|
||||
<property name="transactionalCache">
|
||||
<ref bean="avmLookupCache"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ===================================== -->
|
||||
<!-- AVM Lookup Cache -->
|
||||
<!-- ===================================== -->
|
||||
|
||||
<!-- The cross-transaction shared cache for AVM lookups -->
|
||||
|
||||
<bean name="avmLookupSharedCache" class="org.alfresco.repo.cache.EhCacheAdapter">
|
||||
<property name="cache">
|
||||
<bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
|
||||
<property name="cacheManager">
|
||||
<ref bean="internalEHCacheManager"/>
|
||||
</property>
|
||||
<property name="cacheName">
|
||||
<value>org.alfresco.repo.avm.lookupSharedCache</value>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Transactional cache for AVM lookups -->
|
||||
|
||||
<bean name="avmLookupCache" class="org.alfresco.repo.cache.TransactionalCache">
|
||||
<property name="sharedCache">
|
||||
<ref bean="avmLookupSharedCache"/>
|
||||
</property>
|
||||
<property name="cacheManager">
|
||||
<ref bean="transactionalEHCacheManager"/>
|
||||
</property>
|
||||
<property name="name">
|
||||
<value>org.alfresco.repo.avm.lookupTransactionalCache</value>
|
||||
</property>
|
||||
<property name="maxCacheSize">
|
||||
<value>100</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
@@ -702,6 +702,8 @@
|
||||
org.alfresco.service.cmr.security.AuthorityService.getName=ACL_ALLOW
|
||||
org.alfresco.service.cmr.security.AuthorityService.authorityExists=ACL_METHOD.ROLE_ADMINISTRATOR
|
||||
org.alfresco.service.cmr.security.AuthorityService.getAuthoritiesForUser=ACL_METHOD.ROLE_ADMINISTRATOR
|
||||
org.alfresco.service.cmr.security.AuthorityService.setAuthorityDisplayName=ACL_METHOD.ROLE_ADMINISTRATOR
|
||||
org.alfresco.service.cmr.security.AuthorityService.getAuthorityDisplayName=ACL_ALLOW
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
@@ -294,6 +294,8 @@ public interface ContentModel
|
||||
|
||||
static final QName TYPE_AUTHORITY_CONTAINER = QName.createQName(USER_MODEL_URI, "authorityContainer");
|
||||
static final QName PROP_AUTHORITY_NAME = QName.createQName(USER_MODEL_URI, "authorityName");
|
||||
static final QName PROP_AUTHORITY_DISPLAY_NAME = QName.createQName(USER_MODEL_URI, "authorityDisplayName");
|
||||
|
||||
static final QName ASSOC_MEMBER = QName.createQName(USER_MODEL_URI, "member");
|
||||
static final QName PROP_MEMBERS = QName.createQName(USER_MODEL_URI, "members");
|
||||
|
||||
|
@@ -1,215 +1,38 @@
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2005-2009 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.avm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.repo.avm.util.SimplePath;
|
||||
import org.alfresco.repo.cache.SimpleCache;
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* All lookup traffic goes through here.
|
||||
* @author britt
|
||||
*/
|
||||
public class LookupCache
|
||||
public interface LookupCache
|
||||
{
|
||||
private static Log fgLogger = LogFactory.getLog(LookupCache.class);
|
||||
|
||||
/**
|
||||
* The Map of of keys to lookups.
|
||||
*/
|
||||
private SimpleCache<LookupKey, Lookup> fCache;
|
||||
|
||||
/**
|
||||
* Reference to the Node DAO.
|
||||
*/
|
||||
private AVMNodeDAO fAVMNodeDAO;
|
||||
|
||||
/**
|
||||
* Reference to the Store DAO.
|
||||
*/
|
||||
private AVMStoreDAO fAVMStoreDAO;
|
||||
|
||||
/**
|
||||
* Make one up.
|
||||
*/
|
||||
public LookupCache()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the node dao.
|
||||
* @param dao The dao to set.
|
||||
*/
|
||||
public void setAvmNodeDAO(AVMNodeDAO dao)
|
||||
{
|
||||
fAVMNodeDAO = dao;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the store dao.
|
||||
* @param dao The dao to set.
|
||||
*/
|
||||
public void setAvmStoreDAO(AVMStoreDAO dao)
|
||||
{
|
||||
fAVMStoreDAO = dao;
|
||||
}
|
||||
|
||||
public void setTransactionalCache(SimpleCache<LookupKey, Lookup> cache)
|
||||
{
|
||||
fCache = cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup a path. Try to fulfill the request from the cache.
|
||||
* @param store The AVMStore.
|
||||
* @param version The versions.
|
||||
* @param path The path we are looking up.
|
||||
* @param write Whether this is a write lookup.
|
||||
* @param includeDeleted
|
||||
* @return
|
||||
*/
|
||||
public Lookup lookup(AVMStore store, int version, SimplePath path,
|
||||
boolean write, boolean includeDeleted)
|
||||
{
|
||||
// Create a key object.
|
||||
LookupKey key = new LookupKey(version, path, store.getName(), write, includeDeleted);
|
||||
// Is it in the cache?
|
||||
Lookup found = findInCache(key);
|
||||
// TODO Testing.
|
||||
// found = null;
|
||||
if (found != null)
|
||||
{
|
||||
if (fgLogger.isDebugEnabled())
|
||||
{
|
||||
fgLogger.debug("Cache Hit: " + key + ", " + found.getCurrentNode().getId());
|
||||
}
|
||||
return found;
|
||||
}
|
||||
// Make up a Lookup to hold the results.
|
||||
if (path.size() == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Lookup result = new Lookup(store, store.getName(), version);
|
||||
// Grab the root node to start the lookup.
|
||||
DirectoryNode dir = null;
|
||||
// Versions less than 0 mean get current.
|
||||
if (version < 0)
|
||||
{
|
||||
dir = store.getRoot();
|
||||
}
|
||||
else
|
||||
{
|
||||
VersionRoot vRoot = AVMDAOs.Instance().fVersionRootDAO.getByVersionID(store, version);
|
||||
if (vRoot != null)
|
||||
{
|
||||
dir = vRoot.getRoot();
|
||||
}
|
||||
// dir = fAVMNodeDAO.getAVMStoreRoot(store, version);
|
||||
}
|
||||
if (dir == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
dir = (DirectoryNode)AVMNodeUnwrapper.Unwrap(dir);
|
||||
// Add an entry for the root.
|
||||
result.add(dir, "", true, write);
|
||||
dir = (DirectoryNode)result.getCurrentNode();
|
||||
if (path.size() == 1 && path.get(0).equals(""))
|
||||
{
|
||||
fCache.put(key, result);
|
||||
return result;
|
||||
}
|
||||
// Now look up each path element in sequence up to one
|
||||
// before the end.
|
||||
for (int i = 0; i < path.size() - 1; i++)
|
||||
{
|
||||
if (!AVMRepository.GetInstance().can(null, dir, PermissionService.READ_CHILDREN))
|
||||
{
|
||||
throw new AccessDeniedException("Not allowed to read children: " + path.get(i));
|
||||
}
|
||||
Pair<AVMNode, Boolean> child = dir.lookupChild(result, path.get(i), includeDeleted);
|
||||
if (child == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
// Every element that is not the last needs to be a directory.
|
||||
if (child.getFirst().getType() != AVMNodeType.PLAIN_DIRECTORY &&
|
||||
child.getFirst().getType() != AVMNodeType.LAYERED_DIRECTORY)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
result.add(child.getFirst(), path.get(i), child.getSecond(), write);
|
||||
dir = (DirectoryNode)result.getCurrentNode();
|
||||
}
|
||||
// Now look up the last element.
|
||||
if (!AVMRepository.GetInstance().can(null, dir, PermissionService.READ_CHILDREN))
|
||||
{
|
||||
throw new AccessDeniedException("Not allowed to read children: " + path.get(path.size() - 1));
|
||||
}
|
||||
Pair<AVMNode, Boolean> child = dir.lookupChild(result, path.get(path.size() - 1),
|
||||
includeDeleted);
|
||||
if (child == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
result.add(child.getFirst(), path.get(path.size() - 1), child.getSecond(), write);
|
||||
fCache.put(key, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to find a match in the cache.
|
||||
* @param key The lookup key.
|
||||
* @return A valid for this session Lookup or null if not found.
|
||||
*/
|
||||
private synchronized Lookup findInCache(LookupKey key)
|
||||
{
|
||||
Lookup found = fCache.get(key);
|
||||
if (found != null)
|
||||
{
|
||||
// Get a freshened Lookup.
|
||||
Lookup result = new Lookup(found, fAVMNodeDAO, fAVMStoreDAO);
|
||||
// Check that nothing horrible is wrong. This should
|
||||
// be assertible, but I'll leave the check in for now.
|
||||
if (!result.isValid())
|
||||
{
|
||||
fgLogger.error("Invalid entry in cache: " + key);
|
||||
return null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
// Alternatively for a read lookup a write can match.
|
||||
if (!key.isWrite())
|
||||
{
|
||||
// Make a copy of the key and set it to 'write'
|
||||
LookupKey newKey = new LookupKey(key);
|
||||
newKey.setWrite(true);
|
||||
found = fCache.get(newKey);
|
||||
if (found != null)
|
||||
{
|
||||
// We found it. Make a freshened copy of the Lookup.
|
||||
Lookup result = new Lookup(found, fAVMNodeDAO, fAVMStoreDAO);
|
||||
// Check for badness. This should be assertible but I'll
|
||||
// leave the check in for now.
|
||||
if (!result.isValid())
|
||||
{
|
||||
fgLogger.error("Invalid entry in cache: " + newKey);
|
||||
return null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public Lookup lookup(AVMStore store, int version, SimplePath path, boolean write, boolean includeDeleted);
|
||||
|
||||
// Following are the cache invalidation calls.
|
||||
|
||||
@@ -217,89 +40,23 @@ public class LookupCache
|
||||
* Called when a simple write operation occurs. This
|
||||
* invalidates all read lookups and all layered lookups.
|
||||
*/
|
||||
public synchronized void onWrite(String storeName)
|
||||
{
|
||||
// Invalidate if it's a read lookup in the store, or
|
||||
// any read lookup is it's layered.
|
||||
List<LookupKey> keys = new ArrayList<LookupKey>();
|
||||
for (LookupKey key : fCache.getKeys())
|
||||
{
|
||||
keys.add(key);
|
||||
}
|
||||
for (LookupKey key : keys)
|
||||
{
|
||||
Lookup value = fCache.get(key);
|
||||
if ((key.getStoreName().equals(storeName) &&
|
||||
!key.isWrite()) || value == null ||
|
||||
(!key.isWrite() && value.isLayered()))
|
||||
{
|
||||
if (fgLogger.isDebugEnabled())
|
||||
{
|
||||
fgLogger.debug("Invalidating: " + key + ", " + (value != null ? value.getCurrentNode().getId() : -2));
|
||||
}
|
||||
fCache.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void onWrite(String storeName);
|
||||
|
||||
/**
|
||||
* Called when a delete has occurred in a store. This invalidates both
|
||||
* reads and write lookups in that store.
|
||||
*/
|
||||
public synchronized void onDelete(String storeName)
|
||||
{
|
||||
// Invalidate any entries that are in the store or are layered lookups.
|
||||
List<LookupKey> keys = new ArrayList<LookupKey>();
|
||||
for (LookupKey key : fCache.getKeys())
|
||||
{
|
||||
keys.add(key);
|
||||
}
|
||||
for (LookupKey key : keys)
|
||||
{
|
||||
Lookup value = fCache.get(key);
|
||||
if (key.getStoreName().equals(storeName) ||
|
||||
value == null || value.isLayered())
|
||||
{
|
||||
if (fgLogger.isDebugEnabled())
|
||||
{
|
||||
fgLogger.debug("Invalidating: " + key + ", " + (value != null ? value.getCurrentNode().getId() : -2));
|
||||
}
|
||||
fCache.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void onDelete(String storeName);
|
||||
|
||||
/**
|
||||
* Called when a snapshot occurs in a store. This invalidates write
|
||||
* lookups. Read lookups stay untouched.
|
||||
*/
|
||||
public synchronized void onSnapshot(String storeName)
|
||||
{
|
||||
// Invalidate any entries that in the store and writes or
|
||||
// any layered lookups.
|
||||
List<LookupKey> keys = new ArrayList<LookupKey>();
|
||||
for (LookupKey key : fCache.getKeys())
|
||||
{
|
||||
keys.add(key);
|
||||
}
|
||||
for (LookupKey key : keys)
|
||||
{
|
||||
Lookup value = fCache.get(key);
|
||||
if ((key.getStoreName().equals(storeName) &&
|
||||
key.isWrite()) ||
|
||||
value == null || value.isLayered())
|
||||
{
|
||||
if (fgLogger.isDebugEnabled())
|
||||
{
|
||||
fgLogger.debug("Invalidating: " + key + ", " + (value != null ? value.getCurrentNode().getId() : -2));
|
||||
}
|
||||
fCache.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void onSnapshot(String storeName);
|
||||
|
||||
/**
|
||||
* Full reset of cache.
|
||||
*/
|
||||
public void reset();
|
||||
|
||||
public synchronized void reset()
|
||||
{
|
||||
fCache.clear();
|
||||
}
|
||||
}
|
||||
|
156
source/java/org/alfresco/repo/avm/NOOPLookupCache.java
Normal file
156
source/java/org/alfresco/repo/avm/NOOPLookupCache.java
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.avm;
|
||||
|
||||
import org.alfresco.repo.avm.util.SimplePath;
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.util.Pair;
|
||||
|
||||
/**
|
||||
* A NO-OP implementation of AVM path lookup cache
|
||||
*/
|
||||
public class NOOPLookupCache implements LookupCache
|
||||
{
|
||||
/**
|
||||
* Make one up.
|
||||
*/
|
||||
public NOOPLookupCache()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup a path.
|
||||
*
|
||||
* @param store The AVMStore.
|
||||
* @param version The versions.
|
||||
* @param path The path we are looking up.
|
||||
* @param write Whether this is a write lookup.
|
||||
* @param includeDeleted
|
||||
* @return
|
||||
*/
|
||||
public Lookup lookup(AVMStore store, int version, SimplePath path,
|
||||
boolean write, boolean includeDeleted)
|
||||
{
|
||||
// Make up a Lookup to hold the results.
|
||||
if (path.size() == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Lookup result = new Lookup(store, store.getName(), version);
|
||||
// Grab the root node to start the lookup.
|
||||
DirectoryNode dir = null;
|
||||
// Versions less than 0 mean get current.
|
||||
if (version < 0)
|
||||
{
|
||||
dir = store.getRoot();
|
||||
}
|
||||
else
|
||||
{
|
||||
VersionRoot vRoot = AVMDAOs.Instance().fVersionRootDAO.getByVersionID(store, version);
|
||||
if (vRoot != null)
|
||||
{
|
||||
dir = vRoot.getRoot();
|
||||
}
|
||||
// dir = fAVMNodeDAO.getAVMStoreRoot(store, version);
|
||||
}
|
||||
if (dir == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
dir = (DirectoryNode)AVMNodeUnwrapper.Unwrap(dir);
|
||||
// Add an entry for the root.
|
||||
result.add(dir, "", true, write);
|
||||
dir = (DirectoryNode)result.getCurrentNode();
|
||||
if (path.size() == 1 && path.get(0).equals(""))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
// Now look up each path element in sequence up to one
|
||||
// before the end.
|
||||
for (int i = 0; i < path.size() - 1; i++)
|
||||
{
|
||||
if (!AVMRepository.GetInstance().can(null, dir, PermissionService.READ_CHILDREN))
|
||||
{
|
||||
throw new AccessDeniedException("Not allowed to read children: " + path.get(i));
|
||||
}
|
||||
Pair<AVMNode, Boolean> child = dir.lookupChild(result, path.get(i), includeDeleted);
|
||||
if (child == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
// Every element that is not the last needs to be a directory.
|
||||
if (child.getFirst().getType() != AVMNodeType.PLAIN_DIRECTORY &&
|
||||
child.getFirst().getType() != AVMNodeType.LAYERED_DIRECTORY)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
result.add(child.getFirst(), path.get(i), child.getSecond(), write);
|
||||
dir = (DirectoryNode)result.getCurrentNode();
|
||||
}
|
||||
// Now look up the last element.
|
||||
if (!AVMRepository.GetInstance().can(null, dir, PermissionService.READ_CHILDREN))
|
||||
{
|
||||
throw new AccessDeniedException("Not allowed to read children: " + path.get(path.size() - 1));
|
||||
}
|
||||
Pair<AVMNode, Boolean> child = dir.lookupChild(result, path.get(path.size() - 1),
|
||||
includeDeleted);
|
||||
if (child == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
result.add(child.getFirst(), path.get(path.size() - 1), child.getSecond(), write);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.avm.LookupCache#onWrite(java.lang.String)
|
||||
*/
|
||||
public void onWrite(String storeName)
|
||||
{
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.avm.LookupCache#onDelete(java.lang.String)
|
||||
*/
|
||||
public void onDelete(String storeName)
|
||||
{
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.avm.LookupCache#onSnapshot(java.lang.String)
|
||||
*/
|
||||
public void onSnapshot(String storeName)
|
||||
{
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.avm.LookupCache#reset()
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
339
source/java/org/alfresco/repo/avm/TransactionalLookupCache.java
Normal file
339
source/java/org/alfresco/repo/avm/TransactionalLookupCache.java
Normal file
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.avm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.repo.avm.util.SimplePath;
|
||||
import org.alfresco.repo.cache.SimpleCache;
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
/**
|
||||
* A Transactional? implementation of AVM path lookup cache
|
||||
*
|
||||
* @author britt
|
||||
*/
|
||||
public class TransactionalLookupCache implements LookupCache, InitializingBean
|
||||
{
|
||||
private static Log fgLogger = LogFactory.getLog(TransactionalLookupCache.class);
|
||||
private static Log fgLoggerInit = LogFactory.getLog(TransactionalLookupCache.class.getName() + ".init");
|
||||
|
||||
|
||||
/**
|
||||
* The Map of of keys to lookups.
|
||||
*/
|
||||
private SimpleCache<LookupKey, Lookup> fCache;
|
||||
|
||||
/**
|
||||
* Reference to the Node DAO.
|
||||
*/
|
||||
private AVMNodeDAO fAVMNodeDAO;
|
||||
|
||||
/**
|
||||
* Reference to the Store DAO.
|
||||
*/
|
||||
private AVMStoreDAO fAVMStoreDAO;
|
||||
|
||||
/**
|
||||
* Make one up.
|
||||
*/
|
||||
public TransactionalLookupCache()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the node dao.
|
||||
* @param dao The dao to set.
|
||||
*/
|
||||
public void setAvmNodeDAO(AVMNodeDAO dao)
|
||||
{
|
||||
fAVMNodeDAO = dao;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the store dao.
|
||||
* @param dao The dao to set.
|
||||
*/
|
||||
public void setAvmStoreDAO(AVMStoreDAO dao)
|
||||
{
|
||||
fAVMStoreDAO = dao;
|
||||
}
|
||||
|
||||
public void setTransactionalCache(SimpleCache<LookupKey, Lookup> cache)
|
||||
{
|
||||
fCache = cache;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
public void afterPropertiesSet() throws Exception
|
||||
{
|
||||
if (fgLoggerInit.isDebugEnabled())
|
||||
fgLoggerInit.debug("Transactional AVM lookup cache initialised");
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup a path. Try to fulfill the request from the cache.
|
||||
* @param store The AVMStore.
|
||||
* @param version The versions.
|
||||
* @param path The path we are looking up.
|
||||
* @param write Whether this is a write lookup.
|
||||
* @param includeDeleted
|
||||
* @return
|
||||
*/
|
||||
public Lookup lookup(AVMStore store, int version, SimplePath path,
|
||||
boolean write, boolean includeDeleted)
|
||||
{
|
||||
// Create a key object.
|
||||
LookupKey key = new LookupKey(version, path, store.getName(), write, includeDeleted);
|
||||
// Is it in the cache?
|
||||
Lookup found = findInCache(key);
|
||||
// TODO Testing.
|
||||
// found = null;
|
||||
if (found != null)
|
||||
{
|
||||
if (fgLogger.isDebugEnabled())
|
||||
{
|
||||
fgLogger.debug("Cache Hit: " + key + ", " + found.getCurrentNode().getId());
|
||||
}
|
||||
return found;
|
||||
}
|
||||
// Make up a Lookup to hold the results.
|
||||
if (path.size() == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Lookup result = new Lookup(store, store.getName(), version);
|
||||
// Grab the root node to start the lookup.
|
||||
DirectoryNode dir = null;
|
||||
// Versions less than 0 mean get current.
|
||||
if (version < 0)
|
||||
{
|
||||
dir = store.getRoot();
|
||||
}
|
||||
else
|
||||
{
|
||||
VersionRoot vRoot = AVMDAOs.Instance().fVersionRootDAO.getByVersionID(store, version);
|
||||
if (vRoot != null)
|
||||
{
|
||||
dir = vRoot.getRoot();
|
||||
}
|
||||
// dir = fAVMNodeDAO.getAVMStoreRoot(store, version);
|
||||
}
|
||||
if (dir == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
dir = (DirectoryNode)AVMNodeUnwrapper.Unwrap(dir);
|
||||
// Add an entry for the root.
|
||||
result.add(dir, "", true, write);
|
||||
dir = (DirectoryNode)result.getCurrentNode();
|
||||
if (path.size() == 1 && path.get(0).equals(""))
|
||||
{
|
||||
fCache.put(key, result);
|
||||
return result;
|
||||
}
|
||||
// Now look up each path element in sequence up to one
|
||||
// before the end.
|
||||
for (int i = 0; i < path.size() - 1; i++)
|
||||
{
|
||||
if (!AVMRepository.GetInstance().can(null, dir, PermissionService.READ_CHILDREN))
|
||||
{
|
||||
throw new AccessDeniedException("Not allowed to read children: " + path.get(i));
|
||||
}
|
||||
Pair<AVMNode, Boolean> child = dir.lookupChild(result, path.get(i), includeDeleted);
|
||||
if (child == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
// Every element that is not the last needs to be a directory.
|
||||
if (child.getFirst().getType() != AVMNodeType.PLAIN_DIRECTORY &&
|
||||
child.getFirst().getType() != AVMNodeType.LAYERED_DIRECTORY)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
result.add(child.getFirst(), path.get(i), child.getSecond(), write);
|
||||
dir = (DirectoryNode)result.getCurrentNode();
|
||||
}
|
||||
// Now look up the last element.
|
||||
if (!AVMRepository.GetInstance().can(null, dir, PermissionService.READ_CHILDREN))
|
||||
{
|
||||
throw new AccessDeniedException("Not allowed to read children: " + path.get(path.size() - 1));
|
||||
}
|
||||
Pair<AVMNode, Boolean> child = dir.lookupChild(result, path.get(path.size() - 1),
|
||||
includeDeleted);
|
||||
if (child == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
result.add(child.getFirst(), path.get(path.size() - 1), child.getSecond(), write);
|
||||
fCache.put(key, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to find a match in the cache.
|
||||
* @param key The lookup key.
|
||||
* @return A valid for this session Lookup or null if not found.
|
||||
*/
|
||||
private synchronized Lookup findInCache(LookupKey key)
|
||||
{
|
||||
Lookup found = fCache.get(key);
|
||||
if (found != null)
|
||||
{
|
||||
// Get a freshened Lookup.
|
||||
Lookup result = new Lookup(found, fAVMNodeDAO, fAVMStoreDAO);
|
||||
// Check that nothing horrible is wrong. This should
|
||||
// be assertible, but I'll leave the check in for now.
|
||||
if (!result.isValid())
|
||||
{
|
||||
fgLogger.error("Invalid entry in cache: " + key);
|
||||
return null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
// Alternatively for a read lookup a write can match.
|
||||
if (!key.isWrite())
|
||||
{
|
||||
// Make a copy of the key and set it to 'write'
|
||||
LookupKey newKey = new LookupKey(key);
|
||||
newKey.setWrite(true);
|
||||
found = fCache.get(newKey);
|
||||
if (found != null)
|
||||
{
|
||||
// We found it. Make a freshened copy of the Lookup.
|
||||
Lookup result = new Lookup(found, fAVMNodeDAO, fAVMStoreDAO);
|
||||
// Check for badness. This should be assertible but I'll
|
||||
// leave the check in for now.
|
||||
if (!result.isValid())
|
||||
{
|
||||
fgLogger.error("Invalid entry in cache: " + newKey);
|
||||
return null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Following are the cache invalidation calls.
|
||||
|
||||
/**
|
||||
* Called when a simple write operation occurs. This
|
||||
* invalidates all read lookups and all layered lookups.
|
||||
*/
|
||||
public synchronized void onWrite(String storeName)
|
||||
{
|
||||
// Invalidate if it's a read lookup in the store, or
|
||||
// any read lookup is it's layered.
|
||||
List<LookupKey> keys = new ArrayList<LookupKey>();
|
||||
for (LookupKey key : fCache.getKeys())
|
||||
{
|
||||
keys.add(key);
|
||||
}
|
||||
for (LookupKey key : keys)
|
||||
{
|
||||
Lookup value = fCache.get(key);
|
||||
if ((key.getStoreName().equals(storeName) &&
|
||||
!key.isWrite()) || value == null ||
|
||||
(!key.isWrite() && value.isLayered()))
|
||||
{
|
||||
if (fgLogger.isDebugEnabled())
|
||||
{
|
||||
fgLogger.debug("Invalidating: " + key + ", " + (value != null ? value.getCurrentNode().getId() : -2));
|
||||
}
|
||||
fCache.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a delete has occurred in a store. This invalidates both
|
||||
* reads and write lookups in that store.
|
||||
*/
|
||||
public synchronized void onDelete(String storeName)
|
||||
{
|
||||
// Invalidate any entries that are in the store or are layered lookups.
|
||||
List<LookupKey> keys = new ArrayList<LookupKey>();
|
||||
for (LookupKey key : fCache.getKeys())
|
||||
{
|
||||
keys.add(key);
|
||||
}
|
||||
for (LookupKey key : keys)
|
||||
{
|
||||
Lookup value = fCache.get(key);
|
||||
if (key.getStoreName().equals(storeName) ||
|
||||
value == null || value.isLayered())
|
||||
{
|
||||
if (fgLogger.isDebugEnabled())
|
||||
{
|
||||
fgLogger.debug("Invalidating: " + key + ", " + (value != null ? value.getCurrentNode().getId() : -2));
|
||||
}
|
||||
fCache.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a snapshot occurs in a store. This invalidates write
|
||||
* lookups. Read lookups stay untouched.
|
||||
*/
|
||||
public synchronized void onSnapshot(String storeName)
|
||||
{
|
||||
// Invalidate any entries that in the store and writes or
|
||||
// any layered lookups.
|
||||
List<LookupKey> keys = new ArrayList<LookupKey>();
|
||||
for (LookupKey key : fCache.getKeys())
|
||||
{
|
||||
keys.add(key);
|
||||
}
|
||||
for (LookupKey key : keys)
|
||||
{
|
||||
Lookup value = fCache.get(key);
|
||||
if ((key.getStoreName().equals(storeName) &&
|
||||
key.isWrite()) ||
|
||||
value == null || value.isLayered())
|
||||
{
|
||||
if (fgLogger.isDebugEnabled())
|
||||
{
|
||||
fgLogger.debug("Invalidating: " + key + ", " + (value != null ? value.getCurrentNode().getId() : -2));
|
||||
}
|
||||
fCache.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void reset()
|
||||
{
|
||||
fCache.clear();
|
||||
}
|
||||
}
|
@@ -153,7 +153,7 @@ class AVMStoreDAOHibernate extends HibernateDaoSupport implements
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.avm.AVMStoreDAO#invalidateCache()
|
||||
*/
|
||||
public synchronized void invalidateCache()
|
||||
public void invalidateCache()
|
||||
{
|
||||
fNameCache.clear();
|
||||
}
|
||||
|
@@ -427,6 +427,12 @@ public abstract class AbstractPermissionsDaoComponentImpl implements Permissions
|
||||
return;
|
||||
}
|
||||
|
||||
// avoid NullPointerException if it was not created
|
||||
if (acl == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (acl.getAclType())
|
||||
{
|
||||
case FIXED:
|
||||
|
@@ -90,6 +90,9 @@
|
||||
<property name="usr:members">
|
||||
<type>d:text</type>
|
||||
<multiple>true</multiple>
|
||||
</property>
|
||||
<property name="usr:authorityDisplayName">
|
||||
<type>d:text</type>
|
||||
</property>
|
||||
</properties>
|
||||
<associations>
|
||||
|
@@ -44,8 +44,9 @@ public interface AuthorityDAO
|
||||
*
|
||||
* @param parentName
|
||||
* @param name
|
||||
* @param authorityDisplayName
|
||||
*/
|
||||
void createAuthority(String parentName, String name);
|
||||
void createAuthority(String parentName, String name, String authorityDisplayName);
|
||||
|
||||
/**
|
||||
* Delete an authority.
|
||||
@@ -122,4 +123,20 @@ public interface AuthorityDAO
|
||||
*/
|
||||
public String getAuthorityName(NodeRef authorityRef);
|
||||
|
||||
/**
|
||||
* Get the display name for an authority
|
||||
*
|
||||
* @param authorityName
|
||||
* @return the display name
|
||||
*/
|
||||
String getAuthorityDisplayName(String authorityName);
|
||||
|
||||
/**
|
||||
* Set the display name for an authority
|
||||
*
|
||||
* @param authorityName
|
||||
* @param authorityDisplayName
|
||||
*/
|
||||
void setAuthorityDisplayName(String authorityName, String authorityDisplayName);
|
||||
|
||||
}
|
||||
|
@@ -144,10 +144,11 @@ public class AuthorityDAOImpl implements AuthorityDAO
|
||||
}
|
||||
}
|
||||
|
||||
public void createAuthority(String parentName, String name)
|
||||
public void createAuthority(String parentName, String name, String authorityDisplayName)
|
||||
{
|
||||
HashMap<QName, Serializable> props = new HashMap<QName, Serializable>();
|
||||
props.put(ContentModel.PROP_AUTHORITY_NAME, name);
|
||||
props.put(ContentModel.PROP_AUTHORITY_DISPLAY_NAME, authorityDisplayName);
|
||||
if (parentName != null)
|
||||
{
|
||||
NodeRef parentRef = getAuthorityOrNull(parentName);
|
||||
@@ -543,4 +544,30 @@ public class AuthorityDAOImpl implements AuthorityDAO
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getAuthorityDisplayName(String authorityName)
|
||||
{
|
||||
NodeRef ref = getAuthorityOrNull(authorityName);
|
||||
if(ref == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Serializable value = nodeService.getProperty(ref, ContentModel.PROP_AUTHORITY_DISPLAY_NAME);
|
||||
if(value == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return DefaultTypeConverter.INSTANCE.convert(String.class, value);
|
||||
}
|
||||
|
||||
public void setAuthorityDisplayName(String authorityName, String authorityDisplayName)
|
||||
{
|
||||
NodeRef ref = getAuthorityOrNull(authorityName);
|
||||
if(ref == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
nodeService.setProperty(ref, ContentModel.PROP_AUTHORITY_DISPLAY_NAME, authorityDisplayName);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -261,10 +261,7 @@ public class AuthorityServiceImpl implements AuthorityService, InitializingBean
|
||||
|
||||
public String createAuthority(AuthorityType type, String parentName, String shortName)
|
||||
{
|
||||
checkTypeIsMutable(type);
|
||||
String name = getName(type, shortName);
|
||||
authorityDAO.createAuthority(parentName, name);
|
||||
return name;
|
||||
return createAuthority(type, parentName, shortName, shortName);
|
||||
}
|
||||
|
||||
public void deleteAuthority(String name)
|
||||
@@ -334,4 +331,29 @@ public class AuthorityServiceImpl implements AuthorityService, InitializingBean
|
||||
return authorityDAO.authorityExists(name);
|
||||
}
|
||||
|
||||
public String createAuthority(AuthorityType type, String parentName, String shortName, String authorityDisplayName)
|
||||
{
|
||||
checkTypeIsMutable(type);
|
||||
String name = getName(type, shortName);
|
||||
authorityDAO.createAuthority(parentName, name, authorityDisplayName);
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getAuthorityDisplayName(String name)
|
||||
{
|
||||
String displayName = authorityDAO.getAuthorityDisplayName(name);
|
||||
if(displayName == null)
|
||||
{
|
||||
displayName = getShortName(name);
|
||||
}
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public void setAuthorityDisplayName(String authorityName, String authorityDisplayName)
|
||||
{
|
||||
AuthorityType type = AuthorityType.getAuthorityType(authorityName);
|
||||
checkTypeIsMutable(type);
|
||||
authorityDAO.setAuthorityDisplayName(authorityName, authorityDisplayName);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -867,4 +867,30 @@ public class AuthorityServiceTest extends TestCase
|
||||
properties.put(ContentModel.PROP_ORGID, orgId);
|
||||
return properties;
|
||||
}
|
||||
|
||||
public void testAuthorityDisplayNames()
|
||||
{
|
||||
String authOne = pubAuthorityService.createAuthority(AuthorityType.GROUP, null, "One");
|
||||
assertEquals(pubAuthorityService.getAuthorityDisplayName(authOne), "One");
|
||||
pubAuthorityService.setAuthorityDisplayName(authOne, "Selfish Crocodile");
|
||||
assertEquals(pubAuthorityService.getAuthorityDisplayName(authOne), "Selfish Crocodile");
|
||||
|
||||
String authTwo = pubAuthorityService.createAuthority(AuthorityType.GROUP, null, "Two", "Lamp posts");
|
||||
assertEquals(pubAuthorityService.getAuthorityDisplayName(authTwo), "Lamp posts");
|
||||
pubAuthorityService.setAuthorityDisplayName(authTwo, "Happy Hippos");
|
||||
assertEquals(pubAuthorityService.getAuthorityDisplayName(authTwo), "Happy Hippos");
|
||||
|
||||
assertEquals(pubAuthorityService.getAuthorityDisplayName("GROUP_Loon"), "Loon");
|
||||
assertEquals(pubAuthorityService.getAuthorityDisplayName("ROLE_Gibbon"), "Gibbon");
|
||||
assertEquals(pubAuthorityService.getAuthorityDisplayName("Monkey"), "Monkey");
|
||||
|
||||
authenticationComponent.setCurrentUser("andy");
|
||||
assertEquals(pubAuthorityService.getAuthorityDisplayName(authOne), "Selfish Crocodile");
|
||||
assertEquals(pubAuthorityService.getAuthorityDisplayName(authTwo), "Happy Hippos");
|
||||
assertEquals(pubAuthorityService.getAuthorityDisplayName("GROUP_Loon"), "Loon");
|
||||
assertEquals(pubAuthorityService.getAuthorityDisplayName("GROUP_Loon"), "Loon");
|
||||
assertEquals(pubAuthorityService.getAuthorityDisplayName("ROLE_Gibbon"), "Gibbon");
|
||||
assertEquals(pubAuthorityService.getAuthorityDisplayName("Monkey"), "Monkey");
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -262,4 +262,19 @@ public class SimpleAuthorityServiceImpl implements AuthorityService
|
||||
return authorities;
|
||||
}
|
||||
|
||||
public String createAuthority(AuthorityType type, String parentName, String shortName, String authorityDisplayName)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
public String getAuthorityDisplayName(String name)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
public void setAuthorityDisplayName(String authorityName, String authorityDisplayName)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -113,6 +113,7 @@ public interface AuthorityService
|
||||
* authority is created.
|
||||
* @param shortName -
|
||||
* the short name of the authority to create
|
||||
* this will also be set as the default display name for the authority
|
||||
*
|
||||
* @return the name of the authority (this will be the prefix, if any
|
||||
* associated with the type appended with the short name)
|
||||
@@ -120,6 +121,26 @@ public interface AuthorityService
|
||||
@Auditable(parameters = {"type", "parentName", "shortName"})
|
||||
public String createAuthority(AuthorityType type, String parentName, String shortName);
|
||||
|
||||
/**
|
||||
* Create an authority. If the parent is null thisw method creates a root
|
||||
* authority.
|
||||
*
|
||||
* @param type -
|
||||
* the type of the authority
|
||||
* @param parentName -
|
||||
* the name of the parent authority. If this is null then a root
|
||||
* authority is created.
|
||||
* @param shortName -
|
||||
* the short name of the authority to create
|
||||
* @param authorityDisplayName
|
||||
* the display name for the authority
|
||||
*
|
||||
* @return the name of the authority (this will be the prefix, if any
|
||||
* associated with the type appended with the short name)
|
||||
*/
|
||||
@Auditable(parameters = {"type", "parentName", "shortName", "authorityDisplayName"})
|
||||
public String createAuthority(AuthorityType type, String parentName, String shortName, String authorityDisplayName);
|
||||
|
||||
/**
|
||||
* Set an authority to include another authority. For example, adding a
|
||||
* group to a group or adding a user to a group.
|
||||
@@ -219,4 +240,23 @@ public interface AuthorityService
|
||||
@Auditable(parameters = {"name"})
|
||||
public boolean authorityExists(String name);
|
||||
|
||||
/**
|
||||
* Get the display name for the given authority.
|
||||
*
|
||||
* @param name - the full authority string including any prefix (e.g. GROUP_woof)
|
||||
* @return - the display name
|
||||
*/
|
||||
@Auditable(parameters = {"name"})
|
||||
public String getAuthorityDisplayName(String name);
|
||||
|
||||
/**
|
||||
* Set the display name for the given authority.
|
||||
* Setting the display name is only supported for authorities of type group
|
||||
*
|
||||
* @param authorityName
|
||||
* @param authorityDisplayName
|
||||
*/
|
||||
@Auditable(parameters = {"authorityName", "authorityDisplayName"})
|
||||
public void setAuthorityDisplayName(String authorityName, String authorityDisplayName);
|
||||
|
||||
}
|
||||
|
@@ -28,6 +28,7 @@ import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.config.JNDIConstants;
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
@@ -340,7 +341,7 @@ public final class SandboxFactory extends WCMUtil
|
||||
permissionService.setPermission(dirRef, PermissionService.ALL_AUTHORITIES, PermissionService.READ, true);
|
||||
}
|
||||
|
||||
private void updateStagingAreaManagers(String storeId, NodeRef webProjectNodeRef, final List<String> managers)
|
||||
private void updateStagingAreaManagers(String storeId, final List<String> managers)
|
||||
{
|
||||
// The stores have the mask set in updateSandboxManagers
|
||||
String storeName = WCMUtil.buildStagingStoreName(storeId);
|
||||
@@ -931,9 +932,9 @@ public final class SandboxFactory extends WCMUtil
|
||||
}
|
||||
}
|
||||
|
||||
public void updateSandboxManagers(final String wpStoreId, NodeRef wpNodeRef, List<String> managers)
|
||||
public void updateSandboxManagers(final String wpStoreId, List<String> managers)
|
||||
{
|
||||
// walk existing user sandboxes and reapply manager permissions to include new manager user
|
||||
// walk existing user sandboxes and reapply manager permissions to include new managers
|
||||
List<SandboxInfo> sbInfos = AuthenticationUtil.runAs(new RunAsWork<List<SandboxInfo>>()
|
||||
{
|
||||
public List<SandboxInfo> doWork() throws Exception
|
||||
@@ -951,7 +952,7 @@ public final class SandboxFactory extends WCMUtil
|
||||
}
|
||||
}
|
||||
|
||||
updateStagingAreaManagers(wpStoreId, wpNodeRef, managers);
|
||||
updateStagingAreaManagers(wpStoreId, managers);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -985,6 +986,174 @@ public final class SandboxFactory extends WCMUtil
|
||||
}
|
||||
}
|
||||
|
||||
public void removeSandboxManagers(final String wpStoreId, List<String> managers)
|
||||
{
|
||||
// walk existing user sandboxes and remove manager permissions to exclude old managers
|
||||
List<SandboxInfo> sbInfos = AuthenticationUtil.runAs(new RunAsWork<List<SandboxInfo>>()
|
||||
{
|
||||
public List<SandboxInfo> doWork() throws Exception
|
||||
{
|
||||
return listSandboxes(wpStoreId, AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
|
||||
for (SandboxInfo sbInfo : sbInfos)
|
||||
{
|
||||
if (sbInfo.getSandboxType().equals(SandboxConstants.PROP_SANDBOX_AUTHOR_MAIN))
|
||||
{
|
||||
String username = sbInfo.getName();
|
||||
removeUserSandboxManagers(wpStoreId, managers, username);
|
||||
}
|
||||
}
|
||||
|
||||
removeStagingAreaManagers(wpStoreId, managers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the permissions for the list of sandbox ex-managers.
|
||||
*
|
||||
* @param storeId The store id of the sandbox to update
|
||||
* @param managersToRemove The list of authorities who have had ContentManager role in the web project
|
||||
* @param username Username of the user sandbox to update
|
||||
*/
|
||||
private void removeUserSandboxManagers(String storeId, List<String> managersToRemove, String username)
|
||||
{
|
||||
final String userStoreName = WCMUtil.buildUserMainStoreName(storeId, username);
|
||||
final String previewStoreName = WCMUtil.buildUserPreviewStoreName(storeId, username);
|
||||
|
||||
final NodeRef mainDirRef = AVMNodeConverter.ToNodeRef(-1, WCMUtil.buildStoreRootPath(userStoreName));
|
||||
final NodeRef previewDirRef = AVMNodeConverter.ToNodeRef(-1, WCMUtil.buildStoreRootPath(previewStoreName));
|
||||
for (String manager : managersToRemove)
|
||||
{
|
||||
permissionService.deletePermission(mainDirRef.getStoreRef(), manager, WCMUtil.ROLE_CONTENT_MANAGER);
|
||||
permissionService.deletePermission(previewDirRef.getStoreRef(), manager, WCMUtil.ROLE_CONTENT_MANAGER);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Removes the ContentManager role on staging area to ex-managers.
|
||||
*
|
||||
* @param storeId The store id of the sandbox to update
|
||||
* @param managersToRemove The list of authorities who have had ContentManager role in the web project
|
||||
*/
|
||||
private void removeStagingAreaManagers(String storeId, List<String> managersToRemove)
|
||||
{
|
||||
final String storeName = WCMUtil.buildStagingStoreName(storeId);
|
||||
|
||||
final NodeRef dirRef = AVMNodeConverter.ToNodeRef(-1, WCMUtil.buildStoreRootPath(storeName));
|
||||
for (String manager : managersToRemove)
|
||||
{
|
||||
permissionService.deletePermission(dirRef, manager, WCMUtil.ROLE_CONTENT_MANAGER);
|
||||
|
||||
permissionService.deletePermission(dirRef.getStoreRef(), manager,
|
||||
PermissionService.CHANGE_PERMISSIONS);
|
||||
permissionService.deletePermission(dirRef.getStoreRef(), manager,
|
||||
PermissionService.READ_PERMISSIONS);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void updateSandboxRoles(final String wpStoreId, List<UserRoleWrapper> usersToUpdate, Set<String> permissionsList)
|
||||
{
|
||||
// walk existing user sandboxes and remove manager permissions to exclude old managers
|
||||
List<SandboxInfo> sbInfos = AuthenticationUtil.runAs(new RunAsWork<List<SandboxInfo>>()
|
||||
{
|
||||
public List<SandboxInfo> doWork() throws Exception
|
||||
{
|
||||
return listSandboxes(wpStoreId, AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
|
||||
for (SandboxInfo sbInfo : sbInfos)
|
||||
{
|
||||
if (sbInfo.getSandboxType().equals(SandboxConstants.PROP_SANDBOX_AUTHOR_MAIN))
|
||||
{
|
||||
String username = sbInfo.getName();
|
||||
updateUserSandboxRole(wpStoreId, username ,usersToUpdate, permissionsList);
|
||||
}
|
||||
}
|
||||
|
||||
updateStagingAreaRole(wpStoreId, usersToUpdate, permissionsList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates roles on the sandbox identified by username to users from usersToUpdate list.
|
||||
*
|
||||
* @param storeId The store id of the sandbox to update
|
||||
* @param username Username of the user sandbox to update
|
||||
* @param usersToUpdate The list of users who have role changes
|
||||
* @param permissionsList List of permissions @see org.alfresco.web.bean.wcm.InviteWebsiteUsersWizard.getPermissionsForType(). It is not mandatory.
|
||||
*/
|
||||
private void updateUserSandboxRole(String storeId, String username, List<UserRoleWrapper> usersToUpdate, Set<String> permissionsList)
|
||||
{
|
||||
final String userStoreName = WCMUtil.buildUserMainStoreName(storeId, username);
|
||||
final String previewStoreName = WCMUtil.buildUserPreviewStoreName(storeId, username);
|
||||
|
||||
final NodeRef mainDirRef = AVMNodeConverter.ToNodeRef(-1, WCMUtil.buildStoreRootPath(userStoreName));
|
||||
final NodeRef previewDirRef = AVMNodeConverter.ToNodeRef(-1, WCMUtil.buildStoreRootPath(previewStoreName));
|
||||
|
||||
// If permissionsList is set remove all possible user permissions and set only necessary.
|
||||
// This will fix previous wrong role changes. (paranoid)
|
||||
// For little better performance just set permissionsList to null.
|
||||
// But in this case it removes only previous permission.
|
||||
if (permissionsList != null && permissionsList.size() != 0)
|
||||
{
|
||||
for (UserRoleWrapper user : usersToUpdate)
|
||||
{
|
||||
for (String permission : permissionsList)
|
||||
{
|
||||
permissionService.deletePermission(mainDirRef, user.getUserAuth(), permission);
|
||||
permissionService.deletePermission(previewDirRef, user.getUserAuth(), permission);
|
||||
}
|
||||
|
||||
permissionService.setPermission(mainDirRef, user.getUserAuth(), user.getNewRole(), true);
|
||||
permissionService.setPermission(previewDirRef, user.getUserAuth(), user.getNewRole(), true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (UserRoleWrapper user: usersToUpdate)
|
||||
{
|
||||
permissionService.deletePermission(mainDirRef, user.getUserAuth(), user.getOldRole());
|
||||
permissionService.deletePermission(previewDirRef, user.getUserAuth(), user.getOldRole());
|
||||
permissionService.setPermission(mainDirRef, user.getUserAuth(), user.getNewRole(), true);
|
||||
permissionService.setPermission(previewDirRef, user.getUserAuth(), user.getNewRole(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates roles on staging sandbox to users from usersToUpdate list.
|
||||
*
|
||||
* @param storeId The store id of the sandbox to update
|
||||
* @param usersToUpdate The list of users who have role changes
|
||||
* @param permissionsList List of permissions @see org.alfresco.web.bean.wcm.InviteWebsiteUsersWizard.getPermissionsForType(). It is not mandatory.
|
||||
*/
|
||||
private void updateStagingAreaRole(String storeId, List<UserRoleWrapper> usersToUpdate, Set<String> permissionsList)
|
||||
{
|
||||
final String storeName = WCMUtil.buildStagingStoreName(storeId);
|
||||
final NodeRef dirRef = AVMNodeConverter.ToNodeRef(-1, WCMUtil.buildStoreRootPath(storeName));
|
||||
|
||||
if (permissionsList != null && permissionsList.size() != 0)
|
||||
{
|
||||
for (UserRoleWrapper user : usersToUpdate)
|
||||
{
|
||||
for (String permission : permissionsList)
|
||||
{
|
||||
permissionService.deletePermission(dirRef, user.getUserAuth(), permission);
|
||||
}
|
||||
permissionService.setPermission(dirRef, user.getUserAuth(), user.getNewRole(), true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (UserRoleWrapper user : usersToUpdate)
|
||||
{
|
||||
permissionService.deletePermission(dirRef, user.getUserAuth(), user.getOldRole());
|
||||
permissionService.setPermission(dirRef, user.getUserAuth(), user.getNewRole(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag a named store with a DNS path meta-data attribute.
|
||||
* The DNS meta-data attribute is set to the system path 'store:/www/avm_webapps'
|
||||
@@ -1049,4 +1218,43 @@ public final class SandboxFactory extends WCMUtil
|
||||
logger.debug(" " + name + ": " + props.get(name));
|
||||
}
|
||||
}
|
||||
|
||||
public class UserRoleWrapper
|
||||
{
|
||||
private String newRole;
|
||||
private String oldRole;
|
||||
private String userAuth;
|
||||
|
||||
public UserRoleWrapper(String userAuth, String oldRole, String newRole)
|
||||
{
|
||||
this.userAuth = userAuth;
|
||||
this.oldRole = oldRole;
|
||||
this.newRole = newRole;
|
||||
}
|
||||
|
||||
public String getNewRole()
|
||||
{
|
||||
return newRole;
|
||||
}
|
||||
public void setNewRole(String newRole)
|
||||
{
|
||||
this.newRole = newRole;
|
||||
}
|
||||
public String getOldRole()
|
||||
{
|
||||
return oldRole;
|
||||
}
|
||||
public void setOldRole(String oldRole)
|
||||
{
|
||||
this.oldRole = oldRole;
|
||||
}
|
||||
public String getUserAuth()
|
||||
{
|
||||
return userAuth;
|
||||
}
|
||||
public void setUserAuth(String userAuth)
|
||||
{
|
||||
this.userAuth = userAuth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -69,6 +69,7 @@ import org.alfresco.util.DNSNameMangler;
|
||||
import org.alfresco.util.ParameterCheck;
|
||||
import org.alfresco.wcm.sandbox.SandboxFactory;
|
||||
import org.alfresco.wcm.sandbox.SandboxInfo;
|
||||
import org.alfresco.wcm.sandbox.SandboxFactory.UserRoleWrapper;
|
||||
import org.alfresco.wcm.util.WCMUtil;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -790,9 +791,19 @@ public class WebProjectServiceImpl extends WCMUtil implements WebProjectService
|
||||
|
||||
private String getWebUserRoleImpl(NodeRef wpNodeRef, String userName)
|
||||
{
|
||||
long start = System.currentTimeMillis();
|
||||
NodeRef userRef = getWebUserRef(wpNodeRef, userName);
|
||||
String userRole = null;
|
||||
|
||||
if (userRef != null)
|
||||
{
|
||||
userRole = (String)nodeService.getProperty(userRef, WCMAppModel.PROP_WEBUSERROLE);
|
||||
}
|
||||
|
||||
return userRole;
|
||||
}
|
||||
|
||||
private NodeRef getWebUserRef(NodeRef wpNodeRef, String userName)
|
||||
{
|
||||
StringBuilder query = new StringBuilder(128);
|
||||
query.append("+PARENT:\"").append(wpNodeRef).append("\" ");
|
||||
query.append("+TYPE:\"").append(WCMAppModel.TYPE_WEBUSER).append("\" ");
|
||||
@@ -820,27 +831,23 @@ public class WebProjectServiceImpl extends WCMUtil implements WebProjectService
|
||||
|
||||
if (nodes.size() == 1)
|
||||
{
|
||||
userRole = (String)nodeService.getProperty(nodes.get(0), WCMAppModel.PROP_WEBUSERROLE);
|
||||
return nodes.get(0);
|
||||
}
|
||||
else if (nodes.size() == 0)
|
||||
{
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
logger.trace("getWebProjectUserRole: user role not found for " + userName);
|
||||
logger.trace("getWebUserRef: web user ("+userName+") not found in web project: "+wpNodeRef);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("getWebProjectUserRole: more than one user role found for " + userName);
|
||||
logger.error("getWebUserRef: more than one web user ("+userName+") found in web project: "+wpNodeRef);
|
||||
}
|
||||
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
logger.trace("getWebProjectUserRole: "+userName+" "+userRole+" in "+(System.currentTimeMillis()-start)+" ms");
|
||||
return null;
|
||||
}
|
||||
|
||||
return userRole;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.wcm.webproject.WebProjectService#findWebProjectNodeFromPath(java.lang.String)
|
||||
@@ -889,7 +896,9 @@ public class WebProjectServiceImpl extends WCMUtil implements WebProjectService
|
||||
|
||||
// build a list of managers who will have full permissions on ALL staging areas
|
||||
List<String> managers = new ArrayList<String>(4);
|
||||
Set<String> existingUsers = new HashSet<String>(8);
|
||||
Map<String, NodeRef> webSiteUsers = new HashMap<String, NodeRef>(8);
|
||||
List<String> managersToRemove = new LinkedList<String>();
|
||||
List<UserRoleWrapper> usersToUpdate = new LinkedList<UserRoleWrapper>();
|
||||
|
||||
// retrieve the list of managers from the existing users
|
||||
for (Map.Entry<String, String> userRole : userGroupRoles.entrySet())
|
||||
@@ -906,19 +915,21 @@ public class WebProjectServiceImpl extends WCMUtil implements WebProjectService
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, String> existingUserRoles = listWebUsers(wpNodeRef);
|
||||
for (Map.Entry<String, String> userRole : existingUserRoles.entrySet())
|
||||
List<ChildAssociationRef> userInfoRefs = nodeService.getChildAssocs(wpNodeRef, WCMAppModel.ASSOC_WEBUSER, RegexQNamePattern.MATCH_ALL);
|
||||
|
||||
for (ChildAssociationRef ref : userInfoRefs)
|
||||
{
|
||||
String username = userRole.getKey();
|
||||
String userrole = userRole.getValue();
|
||||
NodeRef userInfoRef = ref.getChildRef();
|
||||
String username = (String)nodeService.getProperty(userInfoRef, WCMAppModel.PROP_WEBUSERNAME);
|
||||
String userrole = (String)nodeService.getProperty(userInfoRef, WCMAppModel.PROP_WEBUSERROLE);
|
||||
|
||||
if (WCMUtil.ROLE_CONTENT_MANAGER.equals(userrole) && managers.contains(username) == false)
|
||||
{
|
||||
managers.add(username);
|
||||
}
|
||||
|
||||
// add each existing user to the exclude this - we cannot add them more than once!
|
||||
existingUsers.add(username);
|
||||
// add each existing user to the map which will be rechecked for update changed user permissions
|
||||
webSiteUsers.put(username, userInfoRef);
|
||||
}
|
||||
|
||||
List<SandboxInfo> sandboxInfoList = new LinkedList<SandboxInfo>();
|
||||
@@ -933,7 +944,7 @@ public class WebProjectServiceImpl extends WCMUtil implements WebProjectService
|
||||
|
||||
for (String userAuth : findNestedUserAuthorities(authority))
|
||||
{
|
||||
if (existingUsers.contains(userAuth) == false)
|
||||
if (webSiteUsers.keySet().contains(userAuth) == false)
|
||||
{
|
||||
if (autoCreateAuthorSandbox)
|
||||
{
|
||||
@@ -955,7 +966,36 @@ public class WebProjectServiceImpl extends WCMUtil implements WebProjectService
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("User '"+userAuth+"' already invited to web project: "+wpNodeRef+"(store id: "+wpStoreId+")");
|
||||
// TODO - split out into separate 'change role'
|
||||
// if user role have been changed then update required properties etc.
|
||||
NodeRef userRef = webSiteUsers.get(userAuth);
|
||||
String oldUserRole = (String)nodeService.getProperty(userRef, WCMAppModel.PROP_WEBUSERROLE);
|
||||
|
||||
if (!role.equals(oldUserRole))
|
||||
{
|
||||
// change in role
|
||||
Map<QName, Serializable> props = nodeService.getProperties(userRef);
|
||||
props.put(WCMAppModel.PROP_WEBUSERNAME, userAuth);
|
||||
props.put(WCMAppModel.PROP_WEBUSERROLE, role);
|
||||
nodeService.setProperties(userRef, props);
|
||||
|
||||
if (WCMUtil.ROLE_CONTENT_MANAGER.equals(role))
|
||||
{
|
||||
managersUpdateRequired = true;
|
||||
}
|
||||
else if (WCMUtil.ROLE_CONTENT_MANAGER.equals(oldUserRole))
|
||||
{
|
||||
managersToRemove.add(userAuth);
|
||||
}
|
||||
|
||||
usersToUpdate.add(sandboxFactory.new UserRoleWrapper(userAuth, oldUserRole, role));
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(userAuth +"'s role has been changed from '" + oldUserRole +
|
||||
"' to '" + role + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -966,7 +1006,14 @@ public class WebProjectServiceImpl extends WCMUtil implements WebProjectService
|
||||
|
||||
if (managersUpdateRequired == true)
|
||||
{
|
||||
sandboxFactory.updateSandboxManagers(wpStoreId, wpNodeRef, managers);
|
||||
sandboxFactory.updateSandboxManagers(wpStoreId, managers);
|
||||
}
|
||||
|
||||
// TODO - split out into separate 'change role'
|
||||
// remove ex-managers from sandboxes
|
||||
if (managersToRemove.size() != 0)
|
||||
{
|
||||
sandboxFactory.removeSandboxManagers(wpStoreId, managersToRemove);
|
||||
}
|
||||
|
||||
// get permissions and roles for a web project folder type
|
||||
@@ -991,6 +1038,13 @@ public class WebProjectServiceImpl extends WCMUtil implements WebProjectService
|
||||
}
|
||||
}
|
||||
|
||||
// TODO - split out into separate 'change role'
|
||||
// update user's roles
|
||||
if (usersToUpdate.size() != 0)
|
||||
{
|
||||
sandboxFactory.updateSandboxRoles(wpStoreId, usersToUpdate, perms);
|
||||
}
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
{
|
||||
logger.info("Invited "+invitedCount+" web users (store id: "+wpStoreId+")");
|
||||
@@ -1027,13 +1081,6 @@ public class WebProjectServiceImpl extends WCMUtil implements WebProjectService
|
||||
WebProjectInfo wpInfo = getWebProject(wpNodeRef);
|
||||
final String wpStoreId = wpInfo.getStoreId();
|
||||
|
||||
if (isWebUser(wpNodeRef, userAuth))
|
||||
{
|
||||
logger.warn("User '"+userAuth+"' already invited to web project: "+wpNodeRef+" (store id: "+wpStoreId+")");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// build a list of managers who will have full permissions on ALL staging areas
|
||||
List<String> managers = new ArrayList<String>(4);
|
||||
|
||||
@@ -1050,6 +1097,49 @@ public class WebProjectServiceImpl extends WCMUtil implements WebProjectService
|
||||
}
|
||||
}
|
||||
|
||||
// get permissions and roles for a web project folder type
|
||||
Set<String> perms = permissionService.getSettablePermissions(WCMAppModel.TYPE_AVMWEBFOLDER);
|
||||
|
||||
NodeRef userRef = getWebUserRef(wpNodeRef, userAuth);
|
||||
if (userRef != null)
|
||||
{
|
||||
// TODO - split out into separate 'change role'
|
||||
// if user role has been changed then update required properties etc.
|
||||
String oldUserRole = (String)nodeService.getProperty(userRef, WCMAppModel.PROP_WEBUSERROLE);
|
||||
if (!role.equals(oldUserRole))
|
||||
{
|
||||
// change in role
|
||||
Map<QName, Serializable> props = nodeService.getProperties(userRef);
|
||||
props.put(WCMAppModel.PROP_WEBUSERNAME, userAuth);
|
||||
props.put(WCMAppModel.PROP_WEBUSERROLE, role);
|
||||
nodeService.setProperties(userRef, props);
|
||||
|
||||
if (WCMUtil.ROLE_CONTENT_MANAGER.equals(role))
|
||||
{
|
||||
managers.add(userAuth);
|
||||
sandboxFactory.updateSandboxManagers(wpStoreId, managers);
|
||||
}
|
||||
else if (WCMUtil.ROLE_CONTENT_MANAGER.equals(oldUserRole))
|
||||
{
|
||||
List<String> managersToRemove = new LinkedList<String>();
|
||||
managersToRemove.add(userAuth);
|
||||
|
||||
sandboxFactory.removeSandboxManagers(wpStoreId, managersToRemove);
|
||||
}
|
||||
|
||||
List<UserRoleWrapper> usersToUpdate = new LinkedList<UserRoleWrapper>();
|
||||
usersToUpdate.add(sandboxFactory.new UserRoleWrapper(userAuth, oldUserRole, role));
|
||||
|
||||
sandboxFactory.updateSandboxRoles(wpStoreId, usersToUpdate, perms);
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
{
|
||||
logger.info("Web user "+userAuth +"'s role has been changed from '" + oldUserRole + "' to '" + role + "' (store id: "+wpStoreId+")");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (autoCreateAuthorSandbox)
|
||||
{
|
||||
// create a sandbox for the user with permissions based on role
|
||||
@@ -1068,7 +1158,7 @@ public class WebProjectServiceImpl extends WCMUtil implements WebProjectService
|
||||
if (WCMUtil.ROLE_CONTENT_MANAGER.equals(role))
|
||||
{
|
||||
managers.add(userAuth);
|
||||
sandboxFactory.updateSandboxManagers(wpStoreId, wpNodeRef, managers);
|
||||
sandboxFactory.updateSandboxManagers(wpStoreId, managers);
|
||||
}
|
||||
|
||||
sandboxFactory.addStagingAreaUser(wpStoreId, userAuth, role);
|
||||
@@ -1076,9 +1166,6 @@ public class WebProjectServiceImpl extends WCMUtil implements WebProjectService
|
||||
// create an app:webuser instance for the user and assoc to the web project node
|
||||
createWebUser(wpNodeRef, userAuth, role);
|
||||
|
||||
// get permissions and roles for a web project folder type
|
||||
Set<String> perms = permissionService.getSettablePermissions(WCMAppModel.TYPE_AVMWEBFOLDER);
|
||||
|
||||
// set permissions for the user
|
||||
for (String permission : perms)
|
||||
{
|
||||
|
Reference in New Issue
Block a user