Compare commits

..

24 Commits

Author SHA1 Message Date
alfresco-build
71b901d16f [maven-release-plugin][skip ci] prepare release 23.3.14.1 2025-09-11 12:43:02 +00:00
Eva Vasques
1819400ac0 [skip tests] Prepare version 23.3.14 (#3567) 2025-09-11 13:39:16 +01:00
alfresco-build
22d6f68c48 [maven-release-plugin][skip ci] prepare for next development iteration 2025-08-25 07:15:13 +00:00
alfresco-build
e18edd2c07 [maven-release-plugin][skip ci] prepare release 23.3.13.2 2025-08-25 07:15:10 +00:00
SatyamSah5
7229105b86 ACS-9991 Allow Content and Metadata extract even if thumbnails are di… (#3542) 2025-08-25 11:55:40 +05:30
alfresco-build
996809e3c2 [maven-release-plugin][skip ci] prepare for next development iteration 2025-08-12 13:12:37 +00:00
alfresco-build
bc76bedc4d [maven-release-plugin][skip ci] prepare release 23.3.13.1 2025-08-12 13:12:35 +00:00
Eva Vasques
179366c974 [skip tests] Prepare next version 23.3.13 (#3517) 2025-08-12 14:09:37 +01:00
alfresco-build
981b98ed88 [maven-release-plugin][skip ci] prepare for next development iteration 2025-08-07 20:45:10 +00:00
alfresco-build
b1469f4410 [maven-release-plugin][skip ci] prepare release 23.3.12.3 2025-08-07 20:45:08 +00:00
Eva Vasques
2e92dab995 MNT-24975 - Repeated IPR groups due to casing inconsistencies on creation (#3509) 2025-08-07 21:03:03 +01:00
alfresco-build
ffcd8973e3 [maven-release-plugin][skip ci] prepare for next development iteration 2025-08-07 13:35:05 +00:00
alfresco-build
b3dcb3ea35 [maven-release-plugin][skip ci] prepare release 23.3.12.2 2025-08-07 13:35:02 +00:00
Eva Vasques
7a49b4c331 ACS-9923 Removing an aspect needs to invoke onUpdateProperties (#3504) (#3505) 2025-08-07 13:50:57 +01:00
alfresco-build
dc0b1988ca [maven-release-plugin][skip ci] prepare for next development iteration 2025-07-30 12:48:19 +00:00
alfresco-build
378abdfe9b [maven-release-plugin][skip ci] prepare release 23.3.12.1 2025-07-30 12:48:17 +00:00
Eva Vasques
5efeeffe3c [skip tests] Prepare Version 23.3.12 (#3494) 2025-07-30 13:45:14 +01:00
alfresco-build
d15a71fddd [maven-release-plugin][skip ci] prepare for next development iteration 2025-07-29 12:22:49 +00:00
alfresco-build
0f2d7a857d [maven-release-plugin][skip ci] prepare release 23.3.11.2 2025-07-29 12:22:46 +00:00
Eva Vasques
e30707fd47 MNT-24975 - Repeated IPR groups due to casing inconsistencies (#3459) (#3492) 2025-07-29 12:27:45 +01:00
alfresco-build
373e0a2d35 [maven-release-plugin][skip ci] prepare for next development iteration 2025-07-28 11:33:07 +00:00
alfresco-build
e5443cf558 [maven-release-plugin][skip ci] prepare release 23.3.11.1 2025-07-28 11:33:04 +00:00
Eva Vasques
8badf8747a [skip tests] Prepare version 23.3.11 (#3490) 2025-07-28 12:29:44 +01:00
alfresco-build
f4274f6900 [maven-release-plugin][skip ci] prepare for next development iteration 2025-06-24 12:29:12 +00:00
32 changed files with 3792 additions and 3449 deletions

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-amps</artifactId> <artifactId>alfresco-community-repo-amps</artifactId>
<version>23.3.10.1</version> <version>23.3.14.1</version>
</parent> </parent>
<modules> <modules>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-parent</artifactId> <artifactId>alfresco-governance-services-community-parent</artifactId>
<version>23.3.10.1</version> <version>23.3.14.1</version>
</parent> </parent>
<modules> <modules>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-automation-community-repo</artifactId> <artifactId>alfresco-governance-services-automation-community-repo</artifactId>
<version>23.3.10.1</version> <version>23.3.14.1</version>
</parent> </parent>
<build> <build>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-parent</artifactId> <artifactId>alfresco-governance-services-community-parent</artifactId>
<version>23.3.10.1</version> <version>23.3.14.1</version>
</parent> </parent>
<modules> <modules>

View File

@@ -119,6 +119,11 @@ rm.patch.v35.holdNewChildAssocPatch.batchSize=1000
rm.haspermissionmap.read=Read rm.haspermissionmap.read=Read
rm.haspermissionmap.write=WriteProperties,AddChildren,ReadContent rm.haspermissionmap.write=WriteProperties,AddChildren,ReadContent
# Extended Permissions
# Enable matching the given username with the correct casing username when retrieving an IPR group.
# Only needs to be used if there are owners that don't have the username in the correct casing.
rm.extendedSecurity.enableUsernameNormalization=false
# #
# Extended auto-version behaviour. If true and other auto-version properties are satisfied, then # Extended auto-version behaviour. If true and other auto-version properties are satisfied, then
# a document will be auto-versioned when its type is changed. # a document will be auto-versioned when its type is changed.

View File

@@ -611,6 +611,7 @@
<property name="authorityService" ref="authorityService"/> <property name="authorityService" ref="authorityService"/>
<property name="permissionService" ref="permissionService"/> <property name="permissionService" ref="permissionService"/>
<property name="transactionService" ref="transactionService"/> <property name="transactionService" ref="transactionService"/>
<property name="enableUsernameNormalization" value="${rm.extendedSecurity.enableUsernameNormalization}" />
</bean> </bean>
<bean id="ExtendedSecurityService" class="org.springframework.aop.framework.ProxyFactoryBean"> <bean id="ExtendedSecurityService" class="org.springframework.aop.framework.ProxyFactoryBean">

View File

@@ -8,7 +8,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-repo-parent</artifactId> <artifactId>alfresco-governance-services-community-repo-parent</artifactId>
<version>23.3.10.1</version> <version>23.3.14.1</version>
</parent> </parent>
<properties> <properties>

View File

@@ -34,6 +34,11 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.extensions.webscripts.ui.common.StringUtils;
import org.alfresco.model.ContentModel;
import org.alfresco.model.RenditionModel; import org.alfresco.model.RenditionModel;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
@@ -42,7 +47,10 @@ import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl; import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl;
import org.alfresco.query.PagingRequest; import org.alfresco.query.PagingRequest;
import org.alfresco.query.PagingResults; import org.alfresco.query.PagingResults;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.security.authority.RMAuthority; import org.alfresco.repo.security.authority.RMAuthority;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException; import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
@@ -54,12 +62,6 @@ import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.service.transaction.TransactionService; import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.Pair; import org.alfresco.util.Pair;
import org.alfresco.util.ParameterCheck; import org.alfresco.util.ParameterCheck;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.extensions.webscripts.ui.common.StringUtils;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
/** /**
* Extended security service implementation. * Extended security service implementation.
@@ -68,9 +70,9 @@ import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransacti
* @since 2.1 * @since 2.1
*/ */
public class ExtendedSecurityServiceImpl extends ServiceBaseImpl public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
implements ExtendedSecurityService, implements ExtendedSecurityService,
RecordsManagementModel, RecordsManagementModel,
ApplicationListener<ContextRefreshedEvent> ApplicationListener<ContextRefreshedEvent>
{ {
/** ipr group names */ /** ipr group names */
static final String ROOT_IPR_GROUP = "INPLACE_RECORD_MANAGEMENT"; static final String ROOT_IPR_GROUP = "INPLACE_RECORD_MANAGEMENT";
@@ -95,8 +97,11 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
/** transaction service */ /** transaction service */
private TransactionService transactionService; private TransactionService transactionService;
private boolean enableUsernameNormalization;
/** /**
* @param filePlanService file plan service * @param filePlanService
* file plan service
*/ */
public void setFilePlanService(FilePlanService filePlanService) public void setFilePlanService(FilePlanService filePlanService)
{ {
@@ -104,7 +109,8 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
} }
/** /**
* @param filePlanRoleService file plan role service * @param filePlanRoleService
* file plan role service
*/ */
public void setFilePlanRoleService(FilePlanRoleService filePlanRoleService) public void setFilePlanRoleService(FilePlanRoleService filePlanRoleService)
{ {
@@ -112,7 +118,8 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
} }
/** /**
* @param authorityService authority service * @param authorityService
* authority service
*/ */
public void setAuthorityService(AuthorityService authorityService) public void setAuthorityService(AuthorityService authorityService)
{ {
@@ -120,7 +127,8 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
} }
/** /**
* @param permissionService permission service * @param permissionService
* permission service
*/ */
public void setPermissionService(PermissionService permissionService) public void setPermissionService(PermissionService permissionService)
{ {
@@ -128,13 +136,23 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
} }
/** /**
* @param transactionService transaction service * @param transactionService
* transaction service
*/ */
public void setTransactionService(TransactionService transactionService) public void setTransactionService(TransactionService transactionService)
{ {
this.transactionService = transactionService; this.transactionService = transactionService;
} }
/**
* @param enableUsernameNormalization
* enable username normalization to ensure correct casing
*/
public void setEnableUsernameNormalization(boolean enableUsernameNormalization)
{
this.enableUsernameNormalization = enableUsernameNormalization;
}
/** /**
* Application context refresh event handler * Application context refresh event handler
*/ */
@@ -142,19 +160,17 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent)
{ {
// run as System on bootstrap // run as System on bootstrap
AuthenticationUtil.runAs(new RunAsWork<Object>() AuthenticationUtil.runAs(new RunAsWork<Object>() {
{
public Object doWork() public Object doWork()
{ {
RetryingTransactionCallback<Void> callback = new RetryingTransactionCallback<Void>() RetryingTransactionCallback<Void> callback = new RetryingTransactionCallback<Void>() {
{
public Void execute() public Void execute()
{ {
// if the root group doesn't exist then create it // if the root group doesn't exist then create it
if (!authorityService.authorityExists(getRootIRPGroup())) if (!authorityService.authorityExists(getRootIRPGroup()))
{ {
authorityService.createAuthority(AuthorityType.GROUP, ROOT_IPR_GROUP, ROOT_IPR_GROUP, authorityService.createAuthority(AuthorityType.GROUP, ROOT_IPR_GROUP, ROOT_IPR_GROUP,
Collections.singleton(RMAuthority.ZONE_APP_RM)); Collections.singleton(RMAuthority.ZONE_APP_RM));
} }
return null; return null;
} }
@@ -174,7 +190,7 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
return GROUP_PREFIX + ROOT_IPR_GROUP; return GROUP_PREFIX + ROOT_IPR_GROUP;
} }
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#hasExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef) * @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#hasExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef)
*/ */
@Override @Override
@@ -224,8 +240,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
/** /**
* Helper to get authorities for a given group * Helper to get authorities for a given group
* *
* @param group group name * @param group
* @return Set<String> immediate authorities * group name
* @return Set<String> immediate authorities
*/ */
private Set<String> getAuthorities(String group) private Set<String> getAuthorities(String group)
{ {
@@ -284,8 +301,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
* <p> * <p>
* Return null if none found. * Return null if none found.
* *
* @param nodeRef node reference * @param nodeRef
* @return Pair<String, String> where first is the read group and second if the write group, null if none found * node reference
* @return Pair<String, String> where first is the read group and second if the write group, null if none found
*/ */
private Pair<String, String> getIPRGroups(NodeRef nodeRef) private Pair<String, String> getIPRGroups(NodeRef nodeRef)
{ {
@@ -321,17 +339,17 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
/** /**
* Given a set of readers and writers find or create the appropriate IPR groups. * Given a set of readers and writers find or create the appropriate IPR groups.
* <p> * <p>
* The IPR groups are named with hashes of the authority lists in order to reduce * The IPR groups are named with hashes of the authority lists in order to reduce the set of groups that require exact match. A further index is used to handle a situation where there is a hash clash, but a difference in the authority lists.
* the set of groups that require exact match. A further index is used to handle
* a situation where there is a hash clash, but a difference in the authority lists.
* <p> * <p>
* When no match is found the groups are created. Once created * When no match is found the groups are created. Once created
* *
* @param filePlan file plan * @param filePlan
* @param readers authorities with read * file plan
* @param writers authorities with write * @param readers
* @return Pair<String, String> where first is the full name of the read group and * authorities with read
* second is the full name of the write group * @param writers
* authorities with write
* @return Pair<String, String> where first is the full name of the read group and second is the full name of the write group
*/ */
private Pair<String, String> createOrFindIPRGroups(Set<String> readers, Set<String> writers) private Pair<String, String> createOrFindIPRGroups(Set<String> readers, Set<String> writers)
{ {
@@ -343,20 +361,28 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
/** /**
* Create or find an IPR group based on the provided prefix and authorities. * Create or find an IPR group based on the provided prefix and authorities.
* *
* @param groupPrefix group prefix * @param groupPrefix
* @param authorities authorities * group prefix
* @return String full group name * @param authorities
* authorities
* @return String full group name
*/ */
private String createOrFindIPRGroup(String groupPrefix, Set<String> authorities) private String createOrFindIPRGroup(String groupPrefix, Set<String> authorities)
{ {
String group = null; String group = null;
// If enabled, the authorities are forced to match the correct casing of the usernames in case they were set
// with the incorrect casing.
// If not, it will just use the authorities as they are.
// In normal circumstances, the authorities are in the correct casing, so this is disabled by default.
Set<String> authoritySet = normalizeAuthorities(authorities);
// find group or determine what the next index is if no group exists or there is a clash // find group or determine what the next index is if no group exists or there is a clash
Pair<String, Integer> groupResult = findIPRGroup(groupPrefix, authorities); Pair<String, Integer> groupResult = findIPRGroup(groupPrefix, authoritySet);
if (groupResult.getFirst() == null) if (groupResult.getFirst() == null)
{ {
group = createIPRGroup(groupPrefix, authorities, groupResult.getSecond()); group = createIPRGroup(groupPrefix, authoritySet, groupResult.getSecond());
} }
else else
{ {
@@ -369,13 +395,13 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
/** /**
* Given a group name prefix and the authorities, finds the exact match existing group. * Given a group name prefix and the authorities, finds the exact match existing group.
* <p> * <p>
* If the group does not exist then the group returned is null and the index shows the next available * If the group does not exist then the group returned is null and the index shows the next available group index for creation.
* group index for creation.
* *
* @param groupPrefix group name prefix * @param groupPrefix
* @param authorities authorities * group name prefix
* @return Pair<String, Integer> where first is the name of the found group, null if none found and second * @param authorities
* if the next available create index * authorities
* @return Pair<String, Integer> where first is the name of the found group, null if none found and second if the next available create index
*/ */
private Pair<String, Integer> findIPRGroup(String groupPrefix, Set<String> authorities) private Pair<String, Integer> findIPRGroup(String groupPrefix, Set<String> authorities)
{ {
@@ -391,12 +417,13 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
while (hasMoreItems == true) while (hasMoreItems == true)
{ {
// get matching authorities // get matching authorities
PagingResults<String> results = authorityService.getAuthorities(AuthorityType.GROUP, PagingResults<String> results = authorityService.getAuthorities(
RMAuthority.ZONE_APP_RM, AuthorityType.GROUP,
groupShortNamePrefix, RMAuthority.ZONE_APP_RM,
false, groupShortNamePrefix,
false, false,
new PagingRequest(MAX_ITEMS*pageCount, MAX_ITEMS)); false,
new PagingRequest(MAX_ITEMS * pageCount, MAX_ITEMS));
// record the total count // record the total count
nextGroupIndex = nextGroupIndex + results.getPage().size(); nextGroupIndex = nextGroupIndex + results.getPage().size();
@@ -413,29 +440,88 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
// determine if there are any more pages to inspect // determine if there are any more pages to inspect
hasMoreItems = results.hasMoreItems(); hasMoreItems = results.hasMoreItems();
pageCount ++; pageCount++;
} }
return new Pair<>(iprGroup, nextGroupIndex); return new Pair<>(iprGroup, nextGroupIndex);
} }
/**
* Given a set of authorities, normalizes the authority names to ensure correct casing.
*
* @param authNames
* @return
*/
private Set<String> normalizeAuthorities(Set<String> authNames)
{
// If disabled or no authorities, return as is
if (!enableUsernameNormalization || authNames == null || authNames.isEmpty())
{
return authNames;
}
Set<String> normalizedAuthorities = new HashSet<>();
for (String authorityName : authNames)
{
normalizedAuthorities.add(normalizeAuthorityName(authorityName));
}
return normalizedAuthorities;
}
/**
* Usernames are case insensitive but affect the IPR group matching when set with different casing. For a given authority of type user, this method normalizes the authority name. If group, it returns the name as-is.
*
* @param authorityName
* the authority name to normalize
* @return the normalized authority name
*/
private String normalizeAuthorityName(String authorityName)
{
if (authorityName == null || authorityName.startsWith(GROUP_PREFIX))
{
return authorityName;
}
// For users, attempt to get the correct casing from the username property of the user node
if (authorityService.authorityExists(authorityName))
{
try
{
NodeRef authorityNodeRef = authorityService.getAuthorityNodeRef(authorityName);
if (authorityNodeRef != null)
{
String username = (String) nodeService.getProperty(authorityNodeRef, ContentModel.PROP_USERNAME);
return username != null ? username : authorityName;
}
}
catch (Exception e)
{
// If anything goes wrong, fallback to the original name
}
}
return authorityName;
}
/** /**
* Determines whether a group exactly matches a list of authorities. * Determines whether a group exactly matches a list of authorities.
* *
* @param authorities list of authorities * @param authorities
* @param group group * list of authorities
* @param group
* group
* @return * @return
*/ */
private boolean isIPRGroupTrueMatch(String group, Set<String> authorities) private boolean isIPRGroupTrueMatch(String group, Set<String> authorities)
{ {
//Remove GROUP_EVERYONE for proper comparison as GROUP_EVERYONE is never included in an IPR group // Remove GROUP_EVERYONE for proper comparison as GROUP_EVERYONE is never included in an IPR group
Set<String> plainAuthorities = new HashSet<String>(); Set<String> plainAuthorities = new HashSet<String>();
if (authorities != null) if (authorities != null)
{ {
plainAuthorities.addAll(authorities); plainAuthorities.addAll(authorities);
plainAuthorities.remove(PermissionService.ALL_AUTHORITIES); plainAuthorities.remove(PermissionService.ALL_AUTHORITIES);
} }
Set<String> contained = authorityService.getContainedAuthorities(null, group, true); Set<String> contained = authorityService.getContainedAuthorities(null, group, true);
return contained.equals(plainAuthorities); return contained.equals(plainAuthorities);
} }
@@ -444,15 +530,17 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
* <p> * <p>
* 'package' scope to help testing. * 'package' scope to help testing.
* *
* @param prefix prefix * @param prefix
* @param authorities authorities * prefix
* @return String group prefix short name * @param authorities
* authorities
* @return String group prefix short name
*/ */
/*package*/ String getIPRGroupPrefixShortName(String prefix, Set<String> authorities) /* package */ String getIPRGroupPrefixShortName(String prefix, Set<String> authorities)
{ {
StringBuilder builder = new StringBuilder(128) StringBuilder builder = new StringBuilder(128)
.append(prefix) .append(prefix)
.append(getAuthoritySetHashCode(authorities)); .append(getAuthoritySetHashCode(authorities));
return builder.toString(); return builder.toString();
} }
@@ -464,13 +552,17 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
* <p> * <p>
* 'package' scope to help testing. * 'package' scope to help testing.
* *
* @param prefix prefix * @param prefix
* @param readers read authorities * prefix
* @param writers write authorities * @param readers
* @param index group index * read authorities
* @return String group short name * @param writers
* write authorities
* @param index
* group index
* @return String group short name
*/ */
/*package*/ String getIPRGroupShortName(String prefix, Set<String> authorities, int index) /* package */ String getIPRGroupShortName(String prefix, Set<String> authorities, int index)
{ {
return getIPRGroupShortName(prefix, authorities, Integer.toString(index)); return getIPRGroupShortName(prefix, authorities, Integer.toString(index));
} }
@@ -480,17 +572,21 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
* <p> * <p>
* Note this excludes the "GROUP_" prefix. * Note this excludes the "GROUP_" prefix.
* *
* @param prefix prefix * @param prefix
* @param readers read authorities * prefix
* @param writers write authorities * @param readers
* @param index group index * read authorities
* @return String group short name * @param writers
* write authorities
* @param index
* group index
* @return String group short name
*/ */
private String getIPRGroupShortName(String prefix, Set<String> authorities, String index) private String getIPRGroupShortName(String prefix, Set<String> authorities, String index)
{ {
StringBuilder builder = new StringBuilder(128) StringBuilder builder = new StringBuilder(128)
.append(getIPRGroupPrefixShortName(prefix, authorities)) .append(getIPRGroupPrefixShortName(prefix, authorities))
.append(index); .append(index);
return builder.toString(); return builder.toString();
} }
@@ -498,8 +594,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
/** /**
* Gets the hashcode value of a set of authorities. * Gets the hashcode value of a set of authorities.
* *
* @param authorities set of authorities * @param authorities
* @return int hash code * set of authorities
* @return int hash code
*/ */
private int getAuthoritySetHashCode(Set<String> authorities) private int getAuthoritySetHashCode(Set<String> authorities)
{ {
@@ -514,10 +611,13 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
/** /**
* Creates a new IPR group. * Creates a new IPR group.
* *
* @param groupNamePrefix group name prefix * @param groupNamePrefix
* @param children child authorities * group name prefix
* @param index group index * @param children
* @return String full name of created group * child authorities
* @param index
* group index
* @return String full name of created group
*/ */
private String createIPRGroup(String groupNamePrefix, Set<String> children, int index) private String createIPRGroup(String groupNamePrefix, Set<String> children, int index)
{ {
@@ -547,7 +647,7 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
} }
} }
} }
catch(DuplicateChildNodeNameException ex) catch (DuplicateChildNodeNameException ex)
{ {
// the group was concurrently created // the group was concurrently created
group = authorityService.getName(AuthorityType.GROUP, groupShortName); group = authorityService.getName(AuthorityType.GROUP, groupShortName);
@@ -559,8 +659,10 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
/** /**
* Assign IPR groups to a node reference with the correct permissions. * Assign IPR groups to a node reference with the correct permissions.
* *
* @param iprGroups iprGroups, first read and second write * @param iprGroups
* @param nodeRef node reference * iprGroups, first read and second write
* @param nodeRef
* node reference
*/ */
private void assignIPRGroupsToNode(Pair<String, String> iprGroups, NodeRef nodeRef) private void assignIPRGroupsToNode(Pair<String, String> iprGroups, NodeRef nodeRef)
{ {
@@ -598,7 +700,8 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
/** /**
* Clear the nodes IPR permissions * Clear the nodes IPR permissions
* *
* @param nodeRef node reference * @param nodeRef
* node reference
*/ */
private void clearPermissions(NodeRef nodeRef, Pair<String, String> iprGroups) private void clearPermissions(NodeRef nodeRef, Pair<String, String> iprGroups)
{ {
@@ -610,7 +713,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#getExtendedReaders(org.alfresco.service.cmr.repository.NodeRef) * @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#getExtendedReaders(org.alfresco.service.cmr.repository.NodeRef)
*/ */
@Override @Deprecated public Set<String> getExtendedReaders(NodeRef nodeRef) @Override
@Deprecated
public Set<String> getExtendedReaders(NodeRef nodeRef)
{ {
return getReaders(nodeRef); return getReaders(nodeRef);
} }
@@ -618,7 +723,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#getExtendedWriters(org.alfresco.service.cmr.repository.NodeRef) * @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#getExtendedWriters(org.alfresco.service.cmr.repository.NodeRef)
*/ */
@Override @Deprecated public Set<String> getExtendedWriters(NodeRef nodeRef) @Override
@Deprecated
public Set<String> getExtendedWriters(NodeRef nodeRef)
{ {
return getWriters(nodeRef); return getWriters(nodeRef);
} }
@@ -626,7 +733,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#addExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set) * @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#addExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set)
*/ */
@Override @Deprecated public void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers) @Override
@Deprecated
public void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers)
{ {
set(nodeRef, readers, writers); set(nodeRef, readers, writers);
} }
@@ -634,7 +743,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#addExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set, boolean) * @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#addExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set, boolean)
*/ */
@Override @Deprecated public void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents) @Override
@Deprecated
public void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents)
{ {
set(nodeRef, readers, writers); set(nodeRef, readers, writers);
} }
@@ -642,7 +753,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeAllExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef) * @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeAllExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef)
*/ */
@Override @Deprecated public void removeAllExtendedSecurity(NodeRef nodeRef) @Override
@Deprecated
public void removeAllExtendedSecurity(NodeRef nodeRef)
{ {
remove(nodeRef); remove(nodeRef);
} }
@@ -650,7 +763,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set) * @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set)
*/ */
@Override @Deprecated public void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers) @Override
@Deprecated
public void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers)
{ {
remove(nodeRef); remove(nodeRef);
} }
@@ -658,7 +773,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set, boolean) * @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set, boolean)
*/ */
@Override @Deprecated public void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String>writers, boolean applyToParents) @Override
@Deprecated
public void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents)
{ {
remove(nodeRef); remove(nodeRef);
} }
@@ -666,7 +783,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeAllExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, boolean) * @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeAllExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, boolean)
*/ */
@Override @Deprecated public void removeAllExtendedSecurity(NodeRef nodeRef, boolean applyToParents) @Override
@Deprecated
public void removeAllExtendedSecurity(NodeRef nodeRef, boolean applyToParents)
{ {
remove(nodeRef); remove(nodeRef);
} }

View File

@@ -52,6 +52,7 @@ import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.alfresco.model.ContentModel;
import org.alfresco.model.RenditionModel; import org.alfresco.model.RenditionModel;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
@@ -67,6 +68,7 @@ import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransacti
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.security.AccessPermission; import org.alfresco.service.cmr.security.AccessPermission;
import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.AuthorityService; import org.alfresco.service.cmr.security.AuthorityService;
@@ -522,6 +524,104 @@ public class ExtendedSecurityServiceImplUnitTest
verify(mockedPermissionService).setPermission(nodeRef, writeGroup, RMPermissionModel.FILING, true); verify(mockedPermissionService).setPermission(nodeRef, writeGroup, RMPermissionModel.FILING, true);
} }
/**
* Given a node with no previous IPR groups assigned
* And having pre-existing IPR groups matching the ones we need
* When I add some read and write authorities but with a different casing
* Then the existing IPR groups are used
*/
@SuppressWarnings("unchecked")
@Test public void addExtendedSecurityWithMixedCasingUsernames()
{
// Have the usernames in the node as the correct usernames but with incorrect casing
String user1 = "UseR";
String user2 = "UseR_w";
// Incorrect IPR Group names
Set<String> diffCasingReaders = Stream.of(user1, GROUP).collect(Collectors.toSet());
Set<String> diffCasingWriters = Stream.of(user2, GROUP_W).collect(Collectors.toSet());
String wrongReadGroupPrefix = extendedSecurityService.getIPRGroupPrefixShortName(READER_GROUP_PREFIX, diffCasingReaders);
String wrongWriteGroupPrefix = extendedSecurityService.getIPRGroupPrefixShortName(WRITER_GROUP_PREFIX, diffCasingWriters);
String wrongReadGroup = wrongReadGroupPrefix + "0";
String wrongWriteGroup = wrongWriteGroupPrefix + "0";
// Correct Group names
String correctReadGroup = readGroupPrefix + "0";
String correctWriteGroup = writeGroupPrefix + "0";
// If queried for the correct groups, return the results
PagingResults<String> mockedCorrectReadPResults = mock(PagingResults.class);
PagingResults<String> mockedCorrectWritePResults = mock(PagingResults.class);
when(mockedCorrectReadPResults.getPage())
.thenReturn(Stream.of(GROUP_PREFIX + correctReadGroup).collect(Collectors.toList()));
when(mockedAuthorityService.getAuthorities(
eq(AuthorityType.GROUP),
eq(RMAuthority.ZONE_APP_RM),
eq(readGroupPrefix),
eq(false),
eq(false),
any(PagingRequest.class)))
.thenReturn(mockedCorrectReadPResults);
when(mockedCorrectWritePResults.getPage())
.thenReturn(Stream.of(GROUP_PREFIX + correctWriteGroup).collect(Collectors.toList()));
when(mockedAuthorityService.getAuthorities(
eq(AuthorityType.GROUP),
eq(RMAuthority.ZONE_APP_RM),
eq(writeGroupPrefix),
eq(false),
eq(false),
any(PagingRequest.class)))
.thenReturn(mockedCorrectWritePResults);
// Don't return results for the incorrect groups (lenient as these may not be called with normalization enabled)
PagingResults<String> mockedWrongReadPResults = mock(PagingResults.class);
PagingResults<String> mockedWrongWritePResults = mock(PagingResults.class);
lenient().when(mockedWrongReadPResults.getPage())
.thenReturn(Collections.emptyList());
lenient().when(mockedAuthorityService.getAuthorities(
eq(AuthorityType.GROUP),
eq(RMAuthority.ZONE_APP_RM),
eq(wrongReadGroupPrefix),
eq(false),
eq(false),
any(PagingRequest.class)))
.thenReturn(mockedWrongReadPResults);
lenient().when(mockedWrongWritePResults.getPage())
.thenReturn(Collections.emptyList());
lenient().when(mockedAuthorityService.getAuthorities(
eq(AuthorityType.GROUP),
eq(RMAuthority.ZONE_APP_RM),
eq(wrongWriteGroupPrefix),
eq(false),
eq(false),
any(PagingRequest.class)))
.thenReturn(mockedWrongWritePResults);
// The users do exist, despite being in a different casing and are able to be retrieved
NodeRef noderefUser1 = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, USER);
when(mockedAuthorityService.authorityExists(user1)).thenReturn(true);
when(mockedAuthorityService.getAuthorityNodeRef(user1)).thenReturn(noderefUser1);
when(mockedNodeService.getProperty(noderefUser1, ContentModel.PROP_USERNAME)).thenReturn(USER);
NodeRef noderefUser2 = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, USER_W);
when(mockedAuthorityService.authorityExists(user2)).thenReturn(true);
when(mockedAuthorityService.getAuthorityNodeRef(user2)).thenReturn(noderefUser2);
when(mockedNodeService.getProperty(noderefUser2, ContentModel.PROP_USERNAME)).thenReturn(USER_W);
// Set the extended security service to normalize usernames
extendedSecurityService.setEnableUsernameNormalization(true);
extendedSecurityService.set(nodeRef, diffCasingReaders, diffCasingWriters);
// Verify that the incorrect read group is not created
verify(mockedAuthorityService, never()).createAuthority(AuthorityType.GROUP, wrongReadGroup, wrongReadGroup, Collections.singleton(RMAuthority.ZONE_APP_RM));
// Verify that the incorrect write group is not created
verify(mockedAuthorityService, never()).createAuthority(AuthorityType.GROUP, wrongWriteGroup, wrongWriteGroup, Collections.singleton(RMAuthority.ZONE_APP_RM));
}
/** /**
* Given a node with no previous IPR groups assigned * Given a node with no previous IPR groups assigned
@@ -571,7 +671,7 @@ public class ExtendedSecurityServiceImplUnitTest
.thenReturn(Stream .thenReturn(Stream
.of(USER_W, AlfMock.generateText()) .of(USER_W, AlfMock.generateText())
.collect(Collectors.toSet())); .collect(Collectors.toSet()));
// add extended security // add extended security
extendedSecurityService.set(nodeRef, READERS, WRITERS); extendedSecurityService.set(nodeRef, READERS, WRITERS);
@@ -895,7 +995,7 @@ public class ExtendedSecurityServiceImplUnitTest
// group names // group names
String readGroup = extendedSecurityService.getIPRGroupShortName(READER_GROUP_FULL_PREFIX, READERS, 0); String readGroup = extendedSecurityService.getIPRGroupShortName(READER_GROUP_FULL_PREFIX, READERS, 0);
String writeGroup = extendedSecurityService.getIPRGroupShortName(WRITER_GROUP_FULL_PREFIX, WRITERS, 0); String writeGroup = extendedSecurityService.getIPRGroupShortName(WRITER_GROUP_FULL_PREFIX, WRITERS, 0);
// setup renditions // setup renditions
NodeRef renditionNodeRef = AlfMock.generateNodeRef(mockedNodeService); NodeRef renditionNodeRef = AlfMock.generateNodeRef(mockedNodeService);
when(mockedNodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_RECORD)) when(mockedNodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_RECORD))
@@ -904,7 +1004,7 @@ public class ExtendedSecurityServiceImplUnitTest
.thenReturn(renditionNodeRef); .thenReturn(renditionNodeRef);
when(mockedNodeService.getChildAssocs(nodeRef, RenditionModel.ASSOC_RENDITION, RegexQNamePattern.MATCH_ALL)) when(mockedNodeService.getChildAssocs(nodeRef, RenditionModel.ASSOC_RENDITION, RegexQNamePattern.MATCH_ALL))
.thenReturn(Collections.singletonList(mockedChildAssociationRef)); .thenReturn(Collections.singletonList(mockedChildAssociationRef));
// setup permissions // setup permissions
Set<AccessPermission> permissions = Stream Set<AccessPermission> permissions = Stream
.of(new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, readGroup, 0), .of(new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, readGroup, 0),
@@ -913,17 +1013,17 @@ public class ExtendedSecurityServiceImplUnitTest
.collect(Collectors.toSet()); .collect(Collectors.toSet());
when(mockedPermissionService.getAllSetPermissions(nodeRef)) when(mockedPermissionService.getAllSetPermissions(nodeRef))
.thenReturn(permissions); .thenReturn(permissions);
// remove extended security // remove extended security
extendedSecurityService.remove(nodeRef); extendedSecurityService.remove(nodeRef);
// verify that the groups permissions have been removed // verify that the groups permissions have been removed
verify(mockedPermissionService).clearPermission(nodeRef, readGroup); verify(mockedPermissionService).clearPermission(nodeRef, readGroup);
verify(mockedPermissionService).clearPermission(nodeRef, writeGroup); verify(mockedPermissionService).clearPermission(nodeRef, writeGroup);
// verify that the groups permissions have been removed from the rendition // verify that the groups permissions have been removed from the rendition
verify(mockedPermissionService).clearPermission(renditionNodeRef, readGroup); verify(mockedPermissionService).clearPermission(renditionNodeRef, readGroup);
verify(mockedPermissionService).clearPermission(renditionNodeRef, writeGroup); verify(mockedPermissionService).clearPermission(renditionNodeRef, writeGroup);
} }
} }

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-repo-parent</artifactId> <artifactId>alfresco-governance-services-community-repo-parent</artifactId>
<version>23.3.10.1</version> <version>23.3.14.1</version>
</parent> </parent>
<build> <build>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId> <artifactId>alfresco-community-repo</artifactId>
<version>23.3.10.1</version> <version>23.3.14.1</version>
</parent> </parent>
<modules> <modules>

View File

@@ -8,7 +8,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-amps</artifactId> <artifactId>alfresco-community-repo-amps</artifactId>
<version>23.3.10.1</version> <version>23.3.14.1</version>
</parent> </parent>
<properties> <properties>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId> <artifactId>alfresco-community-repo</artifactId>
<version>23.3.10.1</version> <version>23.3.14.1</version>
</parent> </parent>
<dependencies> <dependencies>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId> <artifactId>alfresco-community-repo</artifactId>
<version>23.3.10.1</version> <version>23.3.14.1</version>
</parent> </parent>
<properties> <properties>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId> <artifactId>alfresco-community-repo</artifactId>
<version>23.3.10.1</version> <version>23.3.14.1</version>
</parent> </parent>
<dependencies> <dependencies>

View File

@@ -9,6 +9,6 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId> <artifactId>alfresco-community-repo-packaging</artifactId>
<version>23.3.10.1</version> <version>23.3.14.1</version>
</parent> </parent>
</project> </project>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId> <artifactId>alfresco-community-repo-packaging</artifactId>
<version>23.3.10.1</version> <version>23.3.14.1</version>
</parent> </parent>
<properties> <properties>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId> <artifactId>alfresco-community-repo</artifactId>
<version>23.3.10.1</version> <version>23.3.14.1</version>
</parent> </parent>
<modules> <modules>

View File

@@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId> <artifactId>alfresco-community-repo-packaging</artifactId>
<version>23.3.10.1</version> <version>23.3.14.1</version>
</parent> </parent>
<modules> <modules>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId> <artifactId>alfresco-community-repo-tests</artifactId>
<version>23.3.10.1</version> <version>23.3.14.1</version>
</parent> </parent>
<organization> <organization>

View File

@@ -9,7 +9,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId> <artifactId>alfresco-community-repo-tests</artifactId>
<version>23.3.10.1</version> <version>23.3.14.1</version>
</parent> </parent>
<developers> <developers>

View File

@@ -9,7 +9,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId> <artifactId>alfresco-community-repo-tests</artifactId>
<version>23.3.10.1</version> <version>23.3.14.1</version>
</parent> </parent>
<developers> <developers>

View File

@@ -8,7 +8,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId> <artifactId>alfresco-community-repo-tests</artifactId>
<version>23.3.10.1</version> <version>23.3.14.1</version>
</parent> </parent>
<properties> <properties>

View File

@@ -9,7 +9,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId> <artifactId>alfresco-community-repo-tests</artifactId>
<version>23.3.10.1</version> <version>23.3.14.1</version>
</parent> </parent>
<developers> <developers>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId> <artifactId>alfresco-community-repo-packaging</artifactId>
<version>23.3.10.1</version> <version>23.3.14.1</version>
</parent> </parent>
<properties> <properties>

View File

@@ -2,7 +2,7 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>alfresco-community-repo</artifactId> <artifactId>alfresco-community-repo</artifactId>
<version>23.3.10.1</version> <version>23.3.14.1</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>Alfresco Community Repo Parent</name> <name>Alfresco Community Repo Parent</name>
@@ -25,7 +25,7 @@
<properties> <properties>
<acs.version.major>23</acs.version.major> <acs.version.major>23</acs.version.major>
<acs.version.minor>3</acs.version.minor> <acs.version.minor>3</acs.version.minor>
<acs.version.revision>10</acs.version.revision> <acs.version.revision>14</acs.version.revision>
<acs.version.label /> <acs.version.label />
<amp.min.version>${acs.version.major}.0.0</amp.min.version> <amp.min.version>${acs.version.major}.0.0</amp.min.version>
@@ -154,7 +154,7 @@
<connection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</connection> <connection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</connection>
<developerConnection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</developerConnection> <developerConnection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</developerConnection>
<url>https://github.com/Alfresco/alfresco-community-repo</url> <url>https://github.com/Alfresco/alfresco-community-repo</url>
<tag>23.3.10.1</tag> <tag>23.3.14.1</tag>
</scm> </scm>
<distributionManagement> <distributionManagement>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId> <artifactId>alfresco-community-repo</artifactId>
<version>23.3.10.1</version> <version>23.3.14.1</version>
</parent> </parent>
<dependencies> <dependencies>

View File

@@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId> <artifactId>alfresco-community-repo</artifactId>
<version>23.3.10.1</version> <version>23.3.14.1</version>
</parent> </parent>
<dependencies> <dependencies>

View File

@@ -81,11 +81,19 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea
public static final QName DEFAULT_RENDITION_CONTENT_PROP = ContentModel.PROP_CONTENT; public static final QName DEFAULT_RENDITION_CONTENT_PROP = ContentModel.PROP_CONTENT;
public static final String DEFAULT_MIMETYPE = MimetypeMap.MIMETYPE_TEXT_PLAIN; public static final String DEFAULT_MIMETYPE = MimetypeMap.MIMETYPE_TEXT_PLAIN;
public static final String MIMETYPE_METADATA_EXTRACT = "alfresco-metadata-extract";
public static final String MIMETYPE_METADATA_EMBED = "alfresco-metadata-embed";
public static final String DEFAULT_ENCODING = "UTF-8"; public static final String DEFAULT_ENCODING = "UTF-8";
public static final int SOURCE_HAS_NO_CONTENT = -1; public static final int SOURCE_HAS_NO_CONTENT = -1;
public static final int RENDITION2_DOES_NOT_EXIST = -2; public static final int RENDITION2_DOES_NOT_EXIST = -2;
// Allowed mimetypes to support text or metadata extract transforms when thumbnails are disabled.
private static final Set<String> ALLOWED_MIMETYPES = Set.of(
MimetypeMap.MIMETYPE_TEXT_PLAIN,
MIMETYPE_METADATA_EXTRACT,
MIMETYPE_METADATA_EMBED);
private static Log logger = LogFactory.getLog(RenditionService2Impl.class); private static Log logger = LogFactory.getLog(RenditionService2Impl.class);
// As Async transforms and renditions are so similar, this class provides a way to provide the code that is different. // As Async transforms and renditions are so similar, this class provides a way to provide the code that is different.
@@ -288,7 +296,7 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea
{ {
try try
{ {
if (!isEnabled()) if (!isAsyncAllowed(renderOrTransform))
{ {
throw new RenditionService2Exception("Async transforms and renditions are disabled " + throw new RenditionService2Exception("Async transforms and renditions are disabled " +
"(system.thumbnail.generate=false or renditionService2.enabled=false)."); "(system.thumbnail.generate=false or renditionService2.enabled=false).");
@@ -967,4 +975,23 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea
} }
} }
} }
// Checks if the given transform callback is a text extract transform for content indexing or metadata extract/embed.
private boolean isTextOrMetadataExtractTransform(RenderOrTransformCallBack renderOrTransform)
{
RenditionDefinition2 renditionDefinition = renderOrTransform.getRenditionDefinition();
return renditionDefinition != null && ALLOWED_MIMETYPES.contains(renditionDefinition.getTargetMimetype());
}
private boolean isAsyncAllowed(RenderOrTransformCallBack renderOrTransform)
{
// If enabled is false, all async transforms/renditions must be blocked
if (!enabled)
{
return false;
}
// If thumbnails are disabled, allow only text extract or metadata extract/embed transforms
return thumbnailsEnabled || isTextOrMetadataExtractTransform(renderOrTransform);
}
} }

View File

@@ -26,6 +26,12 @@
package org.alfresco.repo.event2; package org.alfresco.repo.event2;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.alfresco.model.ContentModel.PROP_DESCRIPTION; import static org.alfresco.model.ContentModel.PROP_DESCRIPTION;
import java.io.Serializable; import java.io.Serializable;
@@ -35,6 +41,9 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.junit.Test;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.dictionary.M2Model; import org.alfresco.repo.dictionary.M2Model;
@@ -53,7 +62,6 @@ import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.util.GUID; import org.alfresco.util.GUID;
import org.alfresco.util.Pair; import org.alfresco.util.Pair;
import org.junit.Test;
/** /**
* @author Iulian Aftene * @author Iulian Aftene
@@ -66,20 +74,20 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
public void testUpdateNodeResourceContent() public void testUpdateNodeResourceContent()
{ {
ContentService contentService = (ContentService) applicationContext.getBean( ContentService contentService = (ContentService) applicationContext.getBean(
"contentService"); "contentService");
final NodeRef nodeRef = createNode(ContentModel.TYPE_CONTENT); final NodeRef nodeRef = createNode(ContentModel.TYPE_CONTENT);
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEvent(1); RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEvent(1);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(),
resultRepoEvent.getType()); resultRepoEvent.getType());
NodeResource resource = getNodeResource(resultRepoEvent); NodeResource resource = getNodeResource(resultRepoEvent);
assertNull("Content should have been null.", resource.getContent()); assertNull("Content should have been null.", resource.getContent());
retryingTransactionHelper.doInTransaction(() -> { retryingTransactionHelper.doInTransaction(() -> {
ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.TYPE_CONTENT, ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.TYPE_CONTENT,
true); true);
writer.setMimetype(MimetypeMap.MIMETYPE_PDF); writer.setMimetype(MimetypeMap.MIMETYPE_PDF);
writer.setEncoding("UTF-8"); writer.setEncoding("UTF-8");
writer.putContent("test content."); writer.putContent("test content.");
@@ -90,7 +98,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
resultRepoEvent = getRepoEvent(2); resultRepoEvent = getRepoEvent(2);
assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(), assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(),
resultRepoEvent.getType()); resultRepoEvent.getType());
resource = getNodeResource(resultRepoEvent); resource = getNodeResource(resultRepoEvent);
ContentInfo content = resource.getContent(); ContentInfo content = resource.getContent();
@@ -105,7 +113,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
// Update the content again // Update the content again
retryingTransactionHelper.doInTransaction(() -> { retryingTransactionHelper.doInTransaction(() -> {
ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.TYPE_CONTENT, ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.TYPE_CONTENT,
true); true);
writer.setMimetype(MimetypeMap.MIMETYPE_PDF); writer.setMimetype(MimetypeMap.MIMETYPE_PDF);
writer.setEncoding("UTF-8"); writer.setEncoding("UTF-8");
writer.putContent("A quick brown fox jumps over the lazy dog."); writer.putContent("A quick brown fox jumps over the lazy dog.");
@@ -370,7 +378,6 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
assertEquals("new test title", title); assertEquals("new test title", title);
assertEquals("new test title", getLocalizedProperty(resource, "cm:title", defaultLocale)); assertEquals("new test title", getLocalizedProperty(resource, "cm:title", defaultLocale));
resourceBefore = getNodeResourceBefore(3); resourceBefore = getNodeResourceBefore(3);
title = getProperty(resourceBefore, "cm:title"); title = getProperty(resourceBefore, "cm:title");
assertEquals("Wrong old property.", "test title", title); assertEquals("Wrong old property.", "test title", title);
@@ -490,14 +497,14 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
resource = getNodeResource(2); resource = getNodeResource(2);
assertNotNull(resource.getAspectNames()); assertNotNull(resource.getAspectNames());
assertTrue(resource.getAspectNames().contains("cm:versionable")); assertTrue(resource.getAspectNames().contains("cm:versionable"));
//Check all aspects // Check all aspects
Set<String> expectedAspects = new HashSet<>(originalAspects); Set<String> expectedAspects = new HashSet<>(originalAspects);
expectedAspects.add("cm:versionable"); expectedAspects.add("cm:versionable");
assertEquals(expectedAspects, resource.getAspectNames()); assertEquals(expectedAspects, resource.getAspectNames());
// Check properties // Check properties
assertFalse(resource.getProperties().isEmpty()); assertFalse(resource.getProperties().isEmpty());
//Check resourceBefore // Check resourceBefore
NodeResource resourceBefore = getNodeResourceBefore(2); NodeResource resourceBefore = getNodeResourceBefore(2);
assertNotNull(resourceBefore.getAspectNames()); assertNotNull(resourceBefore.getAspectNames());
assertEquals(originalAspects, resourceBefore.getAspectNames()); assertEquals(originalAspects, resourceBefore.getAspectNames());
@@ -544,21 +551,64 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
assertEquals(aspectsBeforeRemove, resourceBefore.getAspectNames()); assertEquals(aspectsBeforeRemove, resourceBefore.getAspectNames());
} }
@Test
public void testRemoveAspectPropertiesTest()
{
final NodeRef nodeRef = createNode(ContentModel.TYPE_CONTENT);
NodeResource resource = getNodeResource(1);
final Set<String> originalAspects = resource.getAspectNames();
assertNotNull(originalAspects);
// Add cm:geographic aspect with properties
retryingTransactionHelper.doInTransaction(() -> {
Map<QName, Serializable> aspectProperties = new HashMap<>();
aspectProperties.put(ContentModel.PROP_LATITUDE, "12.345678");
aspectProperties.put(ContentModel.PROP_LONGITUDE, "12.345678");
nodeService.addAspect(nodeRef, ContentModel.ASPECT_GEOGRAPHIC, aspectProperties);
return null;
});
resource = getNodeResource(2);
Set<String> aspectsBeforeRemove = resource.getAspectNames();
assertNotNull(aspectsBeforeRemove);
assertTrue(aspectsBeforeRemove.contains("cm:geographic"));
// Remove cm:geographic aspect - this automatically removes the properties from the node
retryingTransactionHelper.doInTransaction(() -> {
nodeService.removeAspect(nodeRef, ContentModel.ASPECT_GEOGRAPHIC);
return null;
});
resource = getNodeResource(3);
assertEquals(originalAspects, resource.getAspectNames());
NodeResource resourceBefore = getNodeResourceBefore(3);
assertNotNull(resourceBefore.getAspectNames());
assertEquals(aspectsBeforeRemove, resourceBefore.getAspectNames());
// Resource before should contain cm:latitude and cm:longitude properties
assertNotNull(resourceBefore.getProperties());
assertTrue(resourceBefore.getProperties().containsKey("cm:latitude"));
assertTrue(resourceBefore.getProperties().containsKey("cm:longitude"));
// Resource after should NOT contain cm:latitude and cm:longitude properties
assertNotNull(resource.getProperties());
assertFalse(resource.getProperties().containsKey("cm:latitude"));
assertFalse(resource.getProperties().containsKey("cm:longitude"));
}
@Test @Test
public void testCreateAndUpdateInTheSameTransaction() public void testCreateAndUpdateInTheSameTransaction()
{ {
retryingTransactionHelper.doInTransaction(() -> { retryingTransactionHelper.doInTransaction(() -> {
NodeRef node1 = nodeService.createNode( NodeRef node1 = nodeService.createNode(
rootNodeRef, rootNodeRef,
ContentModel.ASSOC_CHILDREN, ContentModel.ASSOC_CHILDREN,
QName.createQName(TEST_NAMESPACE, GUID.generate()), QName.createQName(TEST_NAMESPACE, GUID.generate()),
ContentModel.TYPE_CONTENT).getChildRef(); ContentModel.TYPE_CONTENT).getChildRef();
nodeService.setProperty(node1, PROP_DESCRIPTION, "test description"); nodeService.setProperty(node1, PROP_DESCRIPTION, "test description");
return null; return null;
}); });
//Create and update node are done in the same transaction so one event is expected // Create and update node are done in the same transaction so one event is expected
// to be generated // to be generated
checkNumOfEvents(1); checkNumOfEvents(1);
} }
@@ -593,8 +643,8 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
assertEquals("Incorrect node type was found", "cm:folder", nodeResource.getNodeType()); assertEquals("Incorrect node type was found", "cm:folder", nodeResource.getNodeType());
NodeResource resourceBefore = getNodeResourceBefore(2); NodeResource resourceBefore = getNodeResourceBefore(2);
assertEquals("Incorrect node type was found","cm:content", resourceBefore.getNodeType()); assertEquals("Incorrect node type was found", "cm:content", resourceBefore.getNodeType());
// assertNotNull(resourceBefore.getModifiedAt()); uncomment this when the issue will be fixed // assertNotNull(resourceBefore.getModifiedAt()); uncomment this when the issue will be fixed
assertNull(resourceBefore.getId()); assertNull(resourceBefore.getId());
assertNull(resourceBefore.getContent()); assertNull(resourceBefore.getContent());
assertNull(resourceBefore.isFile()); assertNull(resourceBefore.isFile());
@@ -624,8 +674,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
m2Type.setTitle("Test type title"); m2Type.setTitle("Test type title");
// Create active model // Create active model
CustomModelDefinition modelDefinition = CustomModelDefinition modelDefinition = retryingTransactionHelper.doInTransaction(() -> customModelService.createCustomModel(model, true));
retryingTransactionHelper.doInTransaction(() -> customModelService.createCustomModel(model, true));
assertNotNull(modelDefinition); assertNotNull(modelDefinition);
assertEquals(modelName, modelDefinition.getName().getLocalName()); assertEquals(modelName, modelDefinition.getName().getLocalName());
@@ -655,7 +704,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType()); assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
assertEquals("cm:content node type was not found", "cm:content", nodeResource.getNodeType()); assertEquals("cm:content node type was not found", "cm:content", nodeResource.getNodeType());
QName typeQName = QName.createQName("{" + namespacePair.getFirst()+ "}" + typeName); QName typeQName = QName.createQName("{" + namespacePair.getFirst() + "}" + typeName);
retryingTransactionHelper.doInTransaction(() -> { retryingTransactionHelper.doInTransaction(() -> {
nodeService.setType(nodeRef, typeQName); nodeService.setType(nodeRef, typeQName);
@@ -757,7 +806,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
// we should have only 1 event, node.Created // we should have only 1 event, node.Created
checkNumOfEvents(1); checkNumOfEvents(1);
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEvent(1); RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEvent(1);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType()); assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
NodeResource nodeResource = getNodeResource(resultRepoEvent); NodeResource nodeResource = getNodeResource(resultRepoEvent);
assertEquals("Incorrect node type was found", "cm:folder", nodeResource.getNodeType()); assertEquals("Incorrect node type was found", "cm:folder", nodeResource.getNodeType());
@@ -783,10 +832,10 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
retryingTransactionHelper.doInTransaction(() -> { retryingTransactionHelper.doInTransaction(() -> {
nodeService.moveNode( nodeService.moveNode(
moveFile, moveFile,
folder2, folder2,
ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS,
QName.createQName(TEST_NAMESPACE)); QName.createQName(TEST_NAMESPACE));
return null; return null;
}); });
@@ -801,7 +850,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
assertEquals("Wrong node parent.", folder1ID, moveFileParentBeforeMove); assertEquals("Wrong node parent.", folder1ID, moveFileParentBeforeMove);
assertEquals("Wrong node parent.", folder2ID, moveFileParentAfterMove); assertEquals("Wrong node parent.", folder2ID, moveFileParentAfterMove);
assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(), assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(),
getRepoEvent(4).getType()); getRepoEvent(4).getType());
assertNull(resourceBefore.getId()); assertNull(resourceBefore.getId());
assertNull(resourceBefore.getName()); assertNull(resourceBefore.getName());
@@ -833,10 +882,10 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
retryingTransactionHelper.doInTransaction(() -> { retryingTransactionHelper.doInTransaction(() -> {
nodeService.moveNode( nodeService.moveNode(
moveFolder, moveFolder,
grandParent, grandParent,
ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS,
QName.createQName(TEST_NAMESPACE)); QName.createQName(TEST_NAMESPACE));
return null; return null;
}); });
@@ -845,15 +894,13 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
final String grandParentID = getNodeResource(1).getId(); final String grandParentID = getNodeResource(1).getId();
final String parentID = getNodeResource(2).getId(); final String parentID = getNodeResource(2).getId();
final String moveFolderParentBeforeMove = final String moveFolderParentBeforeMove = getNodeResourceBefore(4).getPrimaryHierarchy().get(0);
getNodeResourceBefore(4).getPrimaryHierarchy().get(0); final String moveFolderParentAfterMove = getNodeResource(4).getPrimaryHierarchy().get(0);
final String moveFolderParentAfterMove =
getNodeResource(4).getPrimaryHierarchy().get(0);
assertEquals("Wrong node parent.", parentID, moveFolderParentBeforeMove); assertEquals("Wrong node parent.", parentID, moveFolderParentBeforeMove);
assertEquals("Wrong node parent.", grandParentID, moveFolderParentAfterMove); assertEquals("Wrong node parent.", grandParentID, moveFolderParentAfterMove);
assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(), assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(),
getRepoEventWithoutWait(4).getType()); getRepoEventWithoutWait(4).getType());
} }
@Test @Test
@@ -867,28 +914,25 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
retryingTransactionHelper.doInTransaction(() -> { retryingTransactionHelper.doInTransaction(() -> {
nodeService.moveNode( nodeService.moveNode(
grandParent, grandParent,
root2, root2,
ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS,
QName.createQName(TEST_NAMESPACE)); QName.createQName(TEST_NAMESPACE));
return null; return null;
}); });
checkNumOfEvents(6); checkNumOfEvents(6);
final String root2ID = getNodeResource(2).getId(); final String root2ID = getNodeResource(2).getId();
final String grandParentParentAfterMove = final String grandParentParentAfterMove = getNodeResource(6).getPrimaryHierarchy().get(0);
getNodeResource(6).getPrimaryHierarchy().get(0);
assertEquals("Wrong node parent.", root2ID, grandParentParentAfterMove); assertEquals("Wrong node parent.", root2ID, grandParentParentAfterMove);
final String grandParentID = getNodeResource(3).getId(); final String grandParentID = getNodeResource(3).getId();
final String parentIDOfTheParentFolder = final String parentIDOfTheParentFolder = getNodeResource(4).getPrimaryHierarchy().get(0);
getNodeResource(4).getPrimaryHierarchy().get(0);
assertEquals("Wrong node parent.", grandParentID, parentIDOfTheParentFolder); assertEquals("Wrong node parent.", grandParentID, parentIDOfTheParentFolder);
final String parentID = getNodeResource(4).getId(); final String parentID = getNodeResource(4).getId();
final String contentParentID = final String contentParentID = getNodeResource(5).getPrimaryHierarchy().get(0);
getNodeResource(5).getPrimaryHierarchy().get(0);
assertEquals("Wrong node parent.", parentID, contentParentID); assertEquals("Wrong node parent.", parentID, contentParentID);
} }
@@ -906,10 +950,10 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
retryingTransactionHelper.doInTransaction(() -> { retryingTransactionHelper.doInTransaction(() -> {
nodeService.moveNode( nodeService.moveNode(
moveFile, moveFile,
folder2, folder2,
ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS,
QName.createQName(TEST_NAMESPACE)); QName.createQName(TEST_NAMESPACE));
return null; return null;
}); });
@@ -918,8 +962,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
assertTrue("Wrong aspect.", resource.getAspectNames().contains("cm:versionable")); assertTrue("Wrong aspect.", resource.getAspectNames().contains("cm:versionable"));
final String folder2ID = getNodeResource(2).getId(); final String folder2ID = getNodeResource(2).getId();
final String moveFileParentAfterMove = final String moveFileParentAfterMove = getNodeResource(5).getPrimaryHierarchy().get(0);
getNodeResource(5).getPrimaryHierarchy().get(0);
assertEquals("Wrong node parent.", folder2ID, moveFileParentAfterMove); assertEquals("Wrong node parent.", folder2ID, moveFileParentAfterMove);
} }
@@ -935,10 +978,10 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
nodeService.setProperty(moveFile, ContentModel.PROP_NAME, "test_new_name"); nodeService.setProperty(moveFile, ContentModel.PROP_NAME, "test_new_name");
nodeService.moveNode( nodeService.moveNode(
moveFile, moveFile,
folder2, folder2,
ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS,
QName.createQName(TEST_NAMESPACE)); QName.createQName(TEST_NAMESPACE));
return null; return null;
}); });
@@ -946,8 +989,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
assertEquals("test_new_name", resource.getName()); assertEquals("test_new_name", resource.getName());
final String folder2ID = getNodeResource(2).getId(); final String folder2ID = getNodeResource(2).getId();
final String moveFileParentAfterMove = final String moveFileParentAfterMove = getNodeResource(4).getPrimaryHierarchy().get(0);
getNodeResource(4).getPrimaryHierarchy().get(0);
assertEquals("Wrong node parent.", folder2ID, moveFileParentAfterMove); assertEquals("Wrong node parent.", folder2ID, moveFileParentAfterMove);
} }
@@ -958,28 +1000,28 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
retryingTransactionHelper.doInTransaction(() -> { retryingTransactionHelper.doInTransaction(() -> {
NodeRef folder1 = nodeService.createNode( NodeRef folder1 = nodeService.createNode(
rootNodeRef, rootNodeRef,
ContentModel.ASSOC_CHILDREN, ContentModel.ASSOC_CHILDREN,
QName.createQName(TEST_NAMESPACE), QName.createQName(TEST_NAMESPACE),
ContentModel.TYPE_FOLDER).getChildRef(); ContentModel.TYPE_FOLDER).getChildRef();
NodeRef folder2 = nodeService.createNode( NodeRef folder2 = nodeService.createNode(
rootNodeRef, rootNodeRef,
ContentModel.ASSOC_CHILDREN, ContentModel.ASSOC_CHILDREN,
QName.createQName(TEST_NAMESPACE), QName.createQName(TEST_NAMESPACE),
ContentModel.TYPE_FOLDER).getChildRef(); ContentModel.TYPE_FOLDER).getChildRef();
NodeRef fileToMove = nodeService.createNode( NodeRef fileToMove = nodeService.createNode(
folder1, folder1,
ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS,
QName.createQName(TEST_NAMESPACE), QName.createQName(TEST_NAMESPACE),
ContentModel.TYPE_CONTENT).getChildRef(); ContentModel.TYPE_CONTENT).getChildRef();
nodeService.moveNode( nodeService.moveNode(
fileToMove, fileToMove,
folder2, folder2,
ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS,
QName.createQName(TEST_NAMESPACE)); QName.createQName(TEST_NAMESPACE));
assertEquals(folder2, nodeService.getPrimaryParent(fileToMove).getParentRef()); assertEquals(folder2, nodeService.getPrimaryParent(fileToMove).getParentRef());
@@ -989,8 +1031,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
checkNumOfEvents(3); checkNumOfEvents(3);
final String folder2ID = getNodeResource(2).getId(); final String folder2ID = getNodeResource(2).getId();
final String moveFileParentAfterMove = final String moveFileParentAfterMove = getNodeResource(3).getPrimaryHierarchy().get(0);
getNodeResource(3).getPrimaryHierarchy().get(0);
assertEquals("Wrong node parent.", folder2ID, moveFileParentAfterMove); assertEquals("Wrong node parent.", folder2ID, moveFileParentAfterMove);
} }
@@ -1003,7 +1044,6 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
final Set<String> originalAspects = resource.getAspectNames(); final Set<String> originalAspects = resource.getAspectNames();
assertNotNull(originalAspects); assertNotNull(originalAspects);
retryingTransactionHelper.doInTransaction(() -> { retryingTransactionHelper.doInTransaction(() -> {
// Add cm:geographic aspect with default value // Add cm:geographic aspect with default value
nodeService.addAspect(nodeRef, ContentModel.ASPECT_GEOGRAPHIC, null); nodeService.addAspect(nodeRef, ContentModel.ASPECT_GEOGRAPHIC, null);

View File

@@ -39,6 +39,7 @@ import org.junit.Test;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.model.RenditionModel; import org.alfresco.model.RenditionModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
@@ -717,4 +718,57 @@ public class RenditionService2IntegrationTest extends AbstractRenditionIntegrati
renditionService2.setEnabled(true); renditionService2.setEnabled(true);
} }
} }
@Test
public void testTextExtractTransformAllowedWhenThumbnailDisabled()
{
// create a source node
NodeRef sourceNodeRef = createSource(ADMIN, "quick.pdf");
assertNotNull("Node not generated", sourceNodeRef);
String replyQueue = "org.test.queue";
String targetMimetype = MimetypeMap.MIMETYPE_TEXT_PLAIN;
TransformDefinition textExtractTransform = new TransformDefinition(
targetMimetype,
java.util.Collections.emptyMap(),
"clientData",
replyQueue,
"requestId");
renditionService2.setThumbnailsEnabled(false);
try
{
// Should NOT throw, as this is a text extract transform
AuthenticationUtil.runAs(() -> {
transactionService.getRetryingTransactionHelper().doInTransaction(() -> {
renditionService2.transform(sourceNodeRef, textExtractTransform);
return null;
});
return null;
}, ADMIN);
}
finally
{
renditionService2.setThumbnailsEnabled(true);
}
}
@Test
public void testMetadataExtractTransformAllowedWhenThumbnailDisabled()
{
// create a source node
NodeRef sourceNodeRef = createSource(ADMIN, "quick.pdf");
assertNotNull("Node not generated", sourceNodeRef);
renditionService2.setThumbnailsEnabled(false);
try
{
// Should NOT throw, as this is a metadata extract transform
extract(ADMIN, sourceNodeRef);
waitForExtract(ADMIN, sourceNodeRef, true);
}
finally
{
renditionService2.setThumbnailsEnabled(true);
}
}
} }