ACS-5506 Add properties to authority service

This commit is contained in:
MichalKinas
2023-07-07 18:41:14 +02:00
parent 4f4f7cc02f
commit 925a4f4a6a
6 changed files with 202 additions and 50 deletions

View File

@@ -27,6 +27,7 @@ package org.alfresco.rest.api.impl;
import static org.alfresco.repo.security.authentication.AuthenticationUtil.runAsSystem; import static org.alfresco.repo.security.authentication.AuthenticationUtil.runAsSystem;
import java.io.Serializable;
import java.text.Collator; import java.text.Collator;
import java.util.AbstractList; import java.util.AbstractList;
import java.util.ArrayList; import java.util.ArrayList;
@@ -40,6 +41,7 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.alfresco.model.ContentModel;
import org.alfresco.query.CannedQueryPageDetails; import org.alfresco.query.CannedQueryPageDetails;
import org.alfresco.query.EmptyPagingResults; import org.alfresco.query.EmptyPagingResults;
import org.alfresco.query.PagingRequest; import org.alfresco.query.PagingRequest;
@@ -74,7 +76,6 @@ import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AuthorityService; import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.AuthorityType; import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.util.AlfrescoCollator; import org.alfresco.util.AlfrescoCollator;
import org.alfresco.util.Pair; import org.alfresco.util.Pair;
@@ -94,7 +95,6 @@ public class GroupsImpl implements Groups
private static final String ZONE = "zone"; private static final String ZONE = "zone";
private static final String AUTHORITY_NAME = "authorityName"; private static final String AUTHORITY_NAME = "authorityName";
private static final String ERR_MSG_MODIFY_FIXED_AUTHORITY = "Trying to modify a fixed authority"; private static final String ERR_MSG_MODIFY_FIXED_AUTHORITY = "Trying to modify a fixed authority";
private static final QName PROP_DESCRIPTION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "description");
private final static Map<String, String> SORT_PARAMS_TO_NAMES; private final static Map<String, String> SORT_PARAMS_TO_NAMES;
static static
@@ -158,7 +158,13 @@ public class GroupsImpl implements Groups
authorityDisplayName = group.getDisplayName(); authorityDisplayName = group.getDisplayName();
} }
String authority = authorityService.createAuthority(AuthorityType.GROUP, group.getId(), authorityDisplayName, authorityZones); HashMap<QName, Serializable> props = new HashMap<>();
if (StringUtils.isNotEmpty(group.getDescription()))
{
props.put(ContentModel.PROP_DESCRIPTION, group.getDescription());
}
String authority = authorityService.createAuthority(AuthorityType.GROUP, group.getId(), authorityDisplayName, authorityZones, props);
// Set a given child authority to be included by the given parent // Set a given child authority to be included by the given parent
// authorities. // authorities.
@@ -167,12 +173,6 @@ public class GroupsImpl implements Groups
authorityService.addAuthority(group.getParentIds(), authority); authorityService.addAuthority(group.getParentIds(), authority);
} }
if (group.getDescription() != null && !group.getDescription().isEmpty())
{
NodeRef groupNodeRef = authorityService.getAuthorityNodeRef(authority);
nodeService.setProperty(groupNodeRef, PROP_DESCRIPTION, group.getDescription());
}
return getGroup(authority, parameters); return getGroup(authority, parameters);
} }
@@ -190,10 +190,11 @@ public class GroupsImpl implements Groups
handleAuthorityException(ae); handleAuthorityException(ae);
} }
if (group.getDescription() != null && !group.getDescription().isEmpty()) if (StringUtils.isNotEmpty(group.getDescription()))
{ {
NodeRef groupNodeRef = authorityService.getAuthorityNodeRef(authorityService.getName(AuthorityType.GROUP, groupId)); HashMap<QName, Serializable> props = new HashMap<>();
nodeService.setProperty(groupNodeRef, PROP_DESCRIPTION, group.getDescription()); props.put(ContentModel.PROP_DESCRIPTION, group.getDescription());
authorityDAO.setAuthorityProperties(authorityService.getName(AuthorityType.GROUP, groupId), props);
} }
return getGroup(groupId, parameters); return getGroup(groupId, parameters);
@@ -615,9 +616,9 @@ public class GroupsImpl implements Groups
group.setHasSubgroups(!authorityService.getContainedAuthorities(AuthorityType.GROUP, authorityInfo.getAuthorityName(), true).isEmpty()); group.setHasSubgroups(!authorityService.getContainedAuthorities(AuthorityType.GROUP, authorityInfo.getAuthorityName(), true).isEmpty());
NodeRef groupNodeRef = authorityService.getAuthorityNodeRef(authorityInfo.getAuthorityName()); NodeRef groupNodeRef = authorityService.getAuthorityNodeRef(authorityInfo.getAuthorityName());
String description = nodeService.getProperty(groupNodeRef, PROP_DESCRIPTION) != null ? String description = nodeService.getProperty(groupNodeRef, ContentModel.PROP_DESCRIPTION) != null ?
nodeService.getProperty(groupNodeRef, PROP_DESCRIPTION).toString() : nodeService.getProperty(groupNodeRef, ContentModel.PROP_DESCRIPTION).toString() :
""; null;
group.setDescription(description); group.setDescription(description);
// Optionally include // Optionally include
@@ -886,8 +887,7 @@ public class GroupsImpl implements Groups
validateGroupMemberId(groupMemberId); validateGroupMemberId(groupMemberId);
// Verify if groupMemberId is member of groupId // Verify if groupMemberId is member of groupId
AuthorityType authorityType = AuthorityType.getAuthorityType(groupMemberId); Set<String> parents = authorityService.getContainingAuthorities(AuthorityType.GROUP, groupMemberId, true);
Set<String> parents = authorityService.getContainingAuthorities(authorityType, groupMemberId, true);
if (!parents.contains(groupId)) if (!parents.contains(groupId))
{ {
throw new NotFoundException(groupMemberId + " is not member of " + groupId); throw new NotFoundException(groupMemberId + " is not member of " + groupId);

View File

@@ -25,7 +25,9 @@
*/ */
package org.alfresco.repo.security.authority; package org.alfresco.repo.security.authority;
import java.io.Serializable;
import java.util.Collection; import java.util.Collection;
import java.util.Map;
import java.util.Set; import java.util.Set;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
@@ -34,6 +36,7 @@ import org.alfresco.query.PagingResults;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.AuthorityType; import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.AuthorityService.AuthorityFilter; import org.alfresco.service.cmr.security.AuthorityService.AuthorityFilter;
import org.alfresco.service.namespace.QName;
public interface AuthorityDAO public interface AuthorityDAO
{ {
@@ -61,6 +64,11 @@ public interface AuthorityDAO
*/ */
void createAuthority(String name, String authorityDisplayName, Set<String> authorityZones); void createAuthority(String name, String authorityDisplayName, Set<String> authorityZones);
/**
* Create an authority with properties.
*/
void createAuthority(String name, String authorityDisplayName, Set<String> authorityZones, Map<QName, Serializable> properties);
/** /**
* Delete an authority. * Delete an authority.
*/ */
@@ -143,6 +151,11 @@ public interface AuthorityDAO
*/ */
void setAuthorityDisplayName(String authorityName, String authorityDisplayName); void setAuthorityDisplayName(String authorityName, String authorityDisplayName);
/**
* Set the properties for an authority
*/
void setAuthorityProperties(String authorityName, Map<QName, Serializable> properties);
/** /**
* Get root authorities * Get root authorities
*/ */

View File

@@ -92,6 +92,7 @@ import org.alfresco.util.PropertyCheck;
import org.alfresco.util.SearchLanguageConversion; import org.alfresco.util.SearchLanguageConversion;
import org.alfresco.util.registry.NamedObjectRegistry; import org.alfresco.util.registry.NamedObjectRegistry;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
@@ -378,27 +379,35 @@ public class AuthorityDAOImpl implements AuthorityDAO, NodeServicePolicies.Befor
} }
} }
public void createAuthority(String name, String authorityDisplayName, Set<String> authorityZones) public void createAuthority(String name, String authorityDisplayName, Set<String> authorityZones) {
createAuthority(name, authorityDisplayName, authorityZones, null);
}
public void createAuthority(String name, String authorityDisplayName, Set<String> authorityZones, Map<QName, Serializable> properties)
{ {
HashMap<QName, Serializable> props = new HashMap<QName, Serializable>(); HashMap<QName, Serializable> props = new HashMap<>();
/* MNT-11749 : Alfresco allows to create authorities with different char cases, but disallow duplicates */ /* MNT-11749 : Alfresco allows to create authorities with different char cases, but disallow duplicates */
props.put(ContentModel.PROP_NAME, DigestUtils.md5Hex(name)); props.put(ContentModel.PROP_NAME, DigestUtils.md5Hex(name));
props.put(ContentModel.PROP_AUTHORITY_NAME, name); props.put(ContentModel.PROP_AUTHORITY_NAME, name);
props.put(ContentModel.PROP_AUTHORITY_DISPLAY_NAME, authorityDisplayName); props.put(ContentModel.PROP_AUTHORITY_DISPLAY_NAME, authorityDisplayName);
if (MapUtils.isNotEmpty(properties))
{
props.putAll(properties);
}
NodeRef childRef; NodeRef childRef;
NodeRef authorityContainerRef = getAuthorityContainer(); NodeRef authorityContainerRef = getAuthorityContainer();
childRef = nodeService.createNode(authorityContainerRef, ContentModel.ASSOC_CHILDREN, QName.createQName("cm", name, namespacePrefixResolver), childRef = nodeService.createNode(authorityContainerRef, ContentModel.ASSOC_CHILDREN, QName.createQName("cm", name, namespacePrefixResolver),
ContentModel.TYPE_AUTHORITY_CONTAINER, props).getChildRef(); ContentModel.TYPE_AUTHORITY_CONTAINER, props).getChildRef();
if (authorityZones != null) if (authorityZones != null)
{ {
Set<NodeRef> zoneRefs = new HashSet<NodeRef>(authorityZones.size() * 2); Set<NodeRef> zoneRefs = new HashSet<>(authorityZones.size() * 2);
String currentUserDomain = tenantService.getCurrentUserDomain(); String currentUserDomain = tenantService.getCurrentUserDomain();
for (String authorityZone : authorityZones) for (String authorityZone : authorityZones)
{ {
zoneRefs.add(getOrCreateZone(authorityZone)); zoneRefs.add(getOrCreateZone(authorityZone));
zoneAuthorityCache.remove(new Pair<String, String>(currentUserDomain, authorityZone)); zoneAuthorityCache.remove(new Pair<>(currentUserDomain, authorityZone));
} }
zoneAuthorityCache.remove(new Pair<String, String>(currentUserDomain, null)); zoneAuthorityCache.remove(new Pair<>(currentUserDomain, null));
nodeService.addChild(zoneRefs, childRef, ContentModel.ASSOC_IN_ZONE, QName.createQName("cm", name, namespacePrefixResolver)); nodeService.addChild(zoneRefs, childRef, ContentModel.ASSOC_IN_ZONE, QName.createQName("cm", name, namespacePrefixResolver));
} }
authorityLookupCache.put(cacheKey(name), childRef); authorityLookupCache.put(cacheKey(name), childRef);
@@ -1434,6 +1443,16 @@ public class AuthorityDAOImpl implements AuthorityDAO, NodeServicePolicies.Befor
} }
public void setAuthorityProperties(String authorityName, Map<QName, Serializable> properties)
{
NodeRef ref = getAuthorityOrNull(authorityName);
if (ref == null)
{
return;
}
properties.forEach((key, value) -> nodeService.setProperty(ref, key, value));
}
public NodeRef getOrCreateZone(String zoneName) public NodeRef getOrCreateZone(String zoneName)
{ {
return getOrCreateZone(zoneName, true); return getOrCreateZone(zoneName, true);

View File

@@ -25,6 +25,7 @@
*/ */
package org.alfresco.repo.security.authority; package org.alfresco.repo.security.authority;
import java.io.Serializable;
import java.util.AbstractSet; import java.util.AbstractSet;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@@ -32,6 +33,7 @@ import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
@@ -53,6 +55,7 @@ import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.AuthorityType; import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.Pair; import org.alfresco.util.Pair;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.extensions.surf.util.ParameterCheck; import org.springframework.extensions.surf.util.ParameterCheck;
@@ -544,6 +547,14 @@ public class AuthorityServiceImpl implements AuthorityService, InitializingBean
return createAuthority(type, shortName, shortName, getDefaultZones()); return createAuthority(type, shortName, shortName, getDefaultZones());
} }
/**
* {@inheritDoc}
*/
public String createAuthority(AuthorityType type, String shortName, Map<QName, Serializable> properties)
{
return createAuthority(type, shortName, shortName, getDefaultZones(), properties);
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -643,11 +654,20 @@ public class AuthorityServiceImpl implements AuthorityService, InitializingBean
*/ */
public String createAuthority(AuthorityType type, String shortName, String authorityDisplayName, public String createAuthority(AuthorityType type, String shortName, String authorityDisplayName,
Set<String> authorityZones) Set<String> authorityZones)
{
return createAuthority(type, shortName, authorityDisplayName, authorityZones, null);
}
/**
* {@inheritDoc}
*/
public String createAuthority(AuthorityType type, String shortName, String authorityDisplayName,
Set<String> authorityZones, Map<QName, Serializable> properties)
{ {
checkTypeIsMutable(type); checkTypeIsMutable(type);
String name = getName(type, shortName); String name = getName(type, shortName);
authorityDAO.createAuthority(name, authorityDisplayName, authorityZones); authorityDAO.createAuthority(name, authorityDisplayName, authorityZones, properties);
return name; return name;
} }

View File

@@ -25,7 +25,9 @@
*/ */
package org.alfresco.service.cmr.security; package org.alfresco.service.cmr.security;
import java.io.Serializable;
import java.util.Collection; import java.util.Collection;
import java.util.Map;
import java.util.Set; import java.util.Set;
import org.alfresco.api.AlfrescoPublicApi; import org.alfresco.api.AlfrescoPublicApi;
@@ -35,6 +37,7 @@ import org.alfresco.repo.security.authority.AuthorityInfo;
import org.alfresco.service.Auditable; import org.alfresco.service.Auditable;
import org.alfresco.service.NotAuditable; import org.alfresco.service.NotAuditable;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
/** /**
* The service that encapsulates authorities granted to users. * The service that encapsulates authorities granted to users.
@@ -225,6 +228,24 @@ public interface AuthorityService
@Auditable(parameters = {"type", "shortName"}) @Auditable(parameters = {"type", "shortName"})
public String createAuthority(AuthorityType type, String shortName); public String createAuthority(AuthorityType type, String shortName);
/**
* Create an authority with properties.
*
* @param type -
* the type of the authority
* @param shortName -
* the short name of the authority to create
* this will also be set as the default display name for the authority
*
* @param properties -
* properties that will be added to 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", "shortName"})
public String createAuthority(AuthorityType type, String shortName, Map<QName, Serializable> properties);
/** /**
* Create an authority with a display name and zone. * Create an authority with a display name and zone.
* *
@@ -242,6 +263,27 @@ public interface AuthorityService
@Auditable(parameters = {"type", "shortName", "authorityDisplayName", "authorityZones"}) @Auditable(parameters = {"type", "shortName", "authorityDisplayName", "authorityZones"})
public String createAuthority(AuthorityType type, String shortName, String authorityDisplayName, Set<String> authorityZones); public String createAuthority(AuthorityType type, String shortName, String authorityDisplayName, Set<String> authorityZones);
/**
* Create an authority with a display name and zone.
*
* @param type
* the type of the authority
* @param shortName
* the short name of the authority to create
* @param authorityDisplayName
* the display name for the authority
* @param authorityZones
* identifier for external user registry owning the authority or <code>null</code> if not applicable
*
* @param properties -
* properties that will be added to authority
*
* @return the full name of the authority (this will be the prefix, if any associated with the type appended with
* the short name)
*/
@Auditable(parameters = {"type", "shortName", "authorityDisplayName", "authorityZones"})
public String createAuthority(AuthorityType type, String shortName, String authorityDisplayName, Set<String> authorityZones, Map<QName, Serializable> properties);
/** /**
* Set an authority to include another authority. For example, adding a * Set an authority to include another authority. For example, adding a
* group to a group or adding a user to a group. * group to a group or adding a user to a group.

View File

@@ -582,6 +582,65 @@ public class AuthorityServiceTest extends TestCase
} }
} }
public void testCreateGroupAuthWithProperties()
{
String auth;
String groupName = "TESTGROUP";
String prefixedGroupName = "GROUP_TESTGROUP";
String description = "testDesc";
String title = "testTitle";
HashMap<QName, Serializable> props = new HashMap<>();
props.put(ContentModel.PROP_DESCRIPTION, description);
props.put(ContentModel.PROP_TITLE, title);
// create authority with properties and default zones
auth = pubAuthorityService.createAuthority(AuthorityType.GROUP, groupName, props);
assertTrue(pubAuthorityService.authorityExists(prefixedGroupName));
NodeRef nodeRef = pubAuthorityService.getAuthorityNodeRef(auth);
assertEquals(nodeService.getProperty(nodeRef, ContentModel.PROP_DESCRIPTION), description);
assertEquals(nodeService.getProperty(nodeRef, ContentModel.PROP_TITLE), title);
pubAuthorityService.deleteAuthority(auth);
// create authority with zones and properties
Set<String> zones = new HashSet<>();
zones.add("Test1");
zones.add("Test2");
auth = pubAuthorityService.createAuthority(AuthorityType.GROUP, groupName, prefixedGroupName, zones, props);
assertTrue(pubAuthorityService.authorityExists(prefixedGroupName));
nodeRef = pubAuthorityService.getAuthorityNodeRef(auth);
assertEquals(nodeService.getProperty(nodeRef, ContentModel.PROP_DESCRIPTION), description);
assertEquals(nodeService.getProperty(nodeRef, ContentModel.PROP_TITLE), title);
assertEquals(2, pubAuthorityService.getAuthorityZones(auth).size());
pubAuthorityService.deleteAuthority(auth);
}
public void testUpdateAuthorityProperties()
{
String auth;
String groupName = "TESTGROUP";
String prefixedGroupName = "GROUP_TESTGROUP";
String description = "testDesc";
String title = "testTitle";
HashMap<QName, Serializable> props = new HashMap<>();
props.put(ContentModel.PROP_DESCRIPTION, description);
props.put(ContentModel.PROP_TITLE, title);
// create authority with properties
auth = pubAuthorityService.createAuthority(AuthorityType.GROUP, groupName, props);
assertTrue(pubAuthorityService.authorityExists(prefixedGroupName));
// update authority properties
String newDescription = "newTestDesc";
String newTitle = "newTestTitle";
props.put(ContentModel.PROP_DESCRIPTION, newDescription);
props.put(ContentModel.PROP_TITLE, newTitle);
authorityDAO.setAuthorityProperties(auth, props);
NodeRef nodeRef = pubAuthorityService.getAuthorityNodeRef(auth);
assertEquals(nodeService.getProperty(nodeRef, ContentModel.PROP_DESCRIPTION), newDescription);
assertEquals(nodeService.getProperty(nodeRef, ContentModel.PROP_TITLE), newTitle);
pubAuthorityService.deleteAuthority(auth);
}
public void testCreateOwnerAuth() public void testCreateOwnerAuth()
{ {
try try
@@ -1373,7 +1432,6 @@ public class AuthorityServiceTest extends TestCase
properties.put(ContentModel.PROP_ORGID, orgId); properties.put(ContentModel.PROP_ORGID, orgId);
return properties; return properties;
} }
public void testAuthorityDisplayNames() public void testAuthorityDisplayNames()
{ {
String authOne = pubAuthorityService.createAuthority(AuthorityType.GROUP, "One"); String authOne = pubAuthorityService.createAuthority(AuthorityType.GROUP, "One");