mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-09-10 14:11:58 +00:00
Compare commits
40 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
1128011e15 | ||
|
d0cb45de0d | ||
|
2b48195896 | ||
|
fbb95d6a7f | ||
|
502427e852 | ||
|
3ff2d79641 | ||
|
f274b88ece | ||
|
21550ec30b | ||
|
8665267225 | ||
|
984b0bc719 | ||
|
5b89fc0be7 | ||
|
bf3a3382fd | ||
|
14d007fae8 | ||
|
79317ddc9d | ||
|
c0e762fe5e | ||
|
5109b99520 | ||
|
dfc6306331 | ||
|
731f98921f | ||
|
0b21dbdc0a | ||
|
dd928356b8 | ||
|
1844d8bdb9 | ||
|
17eef66f5c | ||
|
1d1f269a70 | ||
|
2ccf6044b8 | ||
|
bdd09784e1 | ||
|
de5d70be46 | ||
|
8cacba0988 | ||
|
60187bf9a2 | ||
|
ff4634be19 | ||
|
9c64b45908 | ||
|
d97d8fba04 | ||
|
368b571d9c | ||
|
e9da7d222b | ||
|
8c059460f9 | ||
|
bd0aaa08b3 | ||
|
93d678dc30 | ||
|
9648189827 | ||
|
9bfd274127 | ||
|
dcf9f65f6b | ||
|
784fae5834 |
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||
<version>23.6.0.1</version>
|
||||
<version>23.6.0.14</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||
<version>23.6.0.1</version>
|
||||
<version>23.6.0.14</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-automation-community-repo</artifactId>
|
||||
<version>23.6.0.1</version>
|
||||
<version>23.6.0.14</version>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
|
@@ -45,7 +45,7 @@ import com.github.dockerjava.netty.NettyDockerCmdExecFactory;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.alfresco.utility.Utility;
|
||||
import org.apache.commons.lang.SystemUtils;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@@ -42,7 +42,7 @@ import org.alfresco.rest.v0.RMRolesAndActionsAPI;
|
||||
import org.alfresco.rest.v0.RecordsAPI;
|
||||
import org.alfresco.rest.v0.RecordCategoriesAPI;
|
||||
import org.alfresco.test.AlfrescoTest;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.testng.annotations.Test;
|
||||
|
@@ -44,7 +44,7 @@ import org.alfresco.rest.v0.service.DispositionScheduleService;
|
||||
import org.alfresco.test.AlfrescoTest;
|
||||
import org.alfresco.utility.model.RepoTestModel;
|
||||
import org.alfresco.utility.model.UserModel;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||
<version>23.6.0.1</version>
|
||||
<version>23.6.0.14</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -119,6 +119,11 @@ rm.patch.v35.holdNewChildAssocPatch.batchSize=1000
|
||||
rm.haspermissionmap.read=Read
|
||||
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
|
||||
# a document will be auto-versioned when its type is changed.
|
||||
|
@@ -611,6 +611,7 @@
|
||||
<property name="authorityService" ref="authorityService"/>
|
||||
<property name="permissionService" ref="permissionService"/>
|
||||
<property name="transactionService" ref="transactionService"/>
|
||||
<property name="enableUsernameNormalization" value="${rm.extendedSecurity.enableUsernameNormalization}" />
|
||||
</bean>
|
||||
|
||||
<bean id="ExtendedSecurityService" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||
<version>23.6.0.1</version>
|
||||
<version>23.6.0.14</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -34,6 +34,11 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
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.module.org_alfresco_module_rm.capability.RMPermissionModel;
|
||||
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.query.PagingRequest;
|
||||
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.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException;
|
||||
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.util.Pair;
|
||||
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.
|
||||
@@ -68,9 +70,9 @@ import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransacti
|
||||
* @since 2.1
|
||||
*/
|
||||
public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
implements ExtendedSecurityService,
|
||||
RecordsManagementModel,
|
||||
ApplicationListener<ContextRefreshedEvent>
|
||||
implements ExtendedSecurityService,
|
||||
RecordsManagementModel,
|
||||
ApplicationListener<ContextRefreshedEvent>
|
||||
{
|
||||
/** ipr group names */
|
||||
static final String ROOT_IPR_GROUP = "INPLACE_RECORD_MANAGEMENT";
|
||||
@@ -95,8 +97,11 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
/** transaction service */
|
||||
private TransactionService transactionService;
|
||||
|
||||
private boolean enableUsernameNormalization;
|
||||
|
||||
/**
|
||||
* @param filePlanService file plan service
|
||||
* @param filePlanService
|
||||
* file plan service
|
||||
*/
|
||||
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)
|
||||
{
|
||||
@@ -112,7 +118,8 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
}
|
||||
|
||||
/**
|
||||
* @param authorityService authority service
|
||||
* @param authorityService
|
||||
* authority service
|
||||
*/
|
||||
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)
|
||||
{
|
||||
@@ -128,13 +136,23 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
}
|
||||
|
||||
/**
|
||||
* @param transactionService transaction service
|
||||
* @param transactionService
|
||||
* transaction service
|
||||
*/
|
||||
public void setTransactionService(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
|
||||
*/
|
||||
@@ -142,19 +160,17 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent)
|
||||
{
|
||||
// run as System on bootstrap
|
||||
AuthenticationUtil.runAs(new RunAsWork<Object>()
|
||||
{
|
||||
AuthenticationUtil.runAs(new RunAsWork<Object>() {
|
||||
public Object doWork()
|
||||
{
|
||||
RetryingTransactionCallback<Void> callback = new RetryingTransactionCallback<Void>()
|
||||
{
|
||||
RetryingTransactionCallback<Void> callback = new RetryingTransactionCallback<Void>() {
|
||||
public Void execute()
|
||||
{
|
||||
// if the root group doesn't exist then create it
|
||||
if (!authorityService.authorityExists(getRootIRPGroup()))
|
||||
{
|
||||
authorityService.createAuthority(AuthorityType.GROUP, ROOT_IPR_GROUP, ROOT_IPR_GROUP,
|
||||
Collections.singleton(RMAuthority.ZONE_APP_RM));
|
||||
Collections.singleton(RMAuthority.ZONE_APP_RM));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -174,7 +190,7 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
return GROUP_PREFIX + ROOT_IPR_GROUP;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#hasExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
@Override
|
||||
@@ -224,8 +240,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
/**
|
||||
* Helper to get authorities for a given group
|
||||
*
|
||||
* @param group group name
|
||||
* @return Set<String> immediate authorities
|
||||
* @param group
|
||||
* group name
|
||||
* @return Set<String> immediate authorities
|
||||
*/
|
||||
private Set<String> getAuthorities(String group)
|
||||
{
|
||||
@@ -284,8 +301,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
* <p>
|
||||
* Return null if none found.
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
* @return Pair<String, String> where first is the read group and second if the write group, null if none found
|
||||
* @param nodeRef
|
||||
* 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)
|
||||
{
|
||||
@@ -321,17 +339,17 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
/**
|
||||
* Given a set of readers and writers find or create the appropriate IPR groups.
|
||||
* <p>
|
||||
* 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 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.
|
||||
* <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 readers authorities with read
|
||||
* @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
|
||||
* @param filePlan
|
||||
* file plan
|
||||
* @param readers
|
||||
* authorities with read
|
||||
* @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)
|
||||
{
|
||||
@@ -343,20 +361,28 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
/**
|
||||
* Create or find an IPR group based on the provided prefix and authorities.
|
||||
*
|
||||
* @param groupPrefix group prefix
|
||||
* @param authorities authorities
|
||||
* @return String full group name
|
||||
* @param groupPrefix
|
||||
* group prefix
|
||||
* @param authorities
|
||||
* authorities
|
||||
* @return String full group name
|
||||
*/
|
||||
private String createOrFindIPRGroup(String groupPrefix, Set<String> authorities)
|
||||
{
|
||||
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
|
||||
Pair<String, Integer> groupResult = findIPRGroup(groupPrefix, authorities);
|
||||
Pair<String, Integer> groupResult = findIPRGroup(groupPrefix, authoritySet);
|
||||
|
||||
if (groupResult.getFirst() == null)
|
||||
{
|
||||
group = createIPRGroup(groupPrefix, authorities, groupResult.getSecond());
|
||||
group = createIPRGroup(groupPrefix, authoritySet, groupResult.getSecond());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -369,13 +395,13 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
/**
|
||||
* Given a group name prefix and the authorities, finds the exact match existing group.
|
||||
* <p>
|
||||
* If the group does not exist then the group returned is null and the index shows the next available
|
||||
* group index for creation.
|
||||
* If the group does not exist then the group returned is null and the index shows the next available group index for creation.
|
||||
*
|
||||
* @param groupPrefix group name prefix
|
||||
* @param authorities 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
|
||||
* @param groupPrefix
|
||||
* group name prefix
|
||||
* @param authorities
|
||||
* 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)
|
||||
{
|
||||
@@ -391,12 +417,13 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
while (hasMoreItems == true)
|
||||
{
|
||||
// get matching authorities
|
||||
PagingResults<String> results = authorityService.getAuthorities(AuthorityType.GROUP,
|
||||
RMAuthority.ZONE_APP_RM,
|
||||
groupShortNamePrefix,
|
||||
false,
|
||||
false,
|
||||
new PagingRequest(MAX_ITEMS*pageCount, MAX_ITEMS));
|
||||
PagingResults<String> results = authorityService.getAuthorities(
|
||||
AuthorityType.GROUP,
|
||||
RMAuthority.ZONE_APP_RM,
|
||||
groupShortNamePrefix,
|
||||
false,
|
||||
false,
|
||||
new PagingRequest(MAX_ITEMS * pageCount, MAX_ITEMS));
|
||||
|
||||
// record the total count
|
||||
nextGroupIndex = nextGroupIndex + results.getPage().size();
|
||||
@@ -413,29 +440,88 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
|
||||
// determine if there are any more pages to inspect
|
||||
hasMoreItems = results.hasMoreItems();
|
||||
pageCount ++;
|
||||
pageCount++;
|
||||
}
|
||||
|
||||
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.
|
||||
*
|
||||
* @param authorities list of authorities
|
||||
* @param group group
|
||||
* @param authorities
|
||||
* list of authorities
|
||||
* @param group
|
||||
* group
|
||||
* @return
|
||||
*/
|
||||
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>();
|
||||
if (authorities != null)
|
||||
{
|
||||
plainAuthorities.addAll(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);
|
||||
}
|
||||
|
||||
@@ -444,15 +530,17 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
* <p>
|
||||
* 'package' scope to help testing.
|
||||
*
|
||||
* @param prefix prefix
|
||||
* @param authorities authorities
|
||||
* @return String group prefix short name
|
||||
* @param prefix
|
||||
* prefix
|
||||
* @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)
|
||||
.append(prefix)
|
||||
.append(getAuthoritySetHashCode(authorities));
|
||||
.append(prefix)
|
||||
.append(getAuthoritySetHashCode(authorities));
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
@@ -464,13 +552,17 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
* <p>
|
||||
* 'package' scope to help testing.
|
||||
*
|
||||
* @param prefix prefix
|
||||
* @param readers read authorities
|
||||
* @param writers write authorities
|
||||
* @param index group index
|
||||
* @return String group short name
|
||||
* @param prefix
|
||||
* prefix
|
||||
* @param readers
|
||||
* read authorities
|
||||
* @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));
|
||||
}
|
||||
@@ -480,17 +572,21 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
* <p>
|
||||
* Note this excludes the "GROUP_" prefix.
|
||||
*
|
||||
* @param prefix prefix
|
||||
* @param readers read authorities
|
||||
* @param writers write authorities
|
||||
* @param index group index
|
||||
* @return String group short name
|
||||
* @param prefix
|
||||
* prefix
|
||||
* @param readers
|
||||
* read authorities
|
||||
* @param writers
|
||||
* write authorities
|
||||
* @param index
|
||||
* group index
|
||||
* @return String group short name
|
||||
*/
|
||||
private String getIPRGroupShortName(String prefix, Set<String> authorities, String index)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder(128)
|
||||
.append(getIPRGroupPrefixShortName(prefix, authorities))
|
||||
.append(index);
|
||||
.append(getIPRGroupPrefixShortName(prefix, authorities))
|
||||
.append(index);
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
@@ -498,8 +594,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
/**
|
||||
* Gets the hashcode value of a set of authorities.
|
||||
*
|
||||
* @param authorities set of authorities
|
||||
* @return int hash code
|
||||
* @param authorities
|
||||
* set of authorities
|
||||
* @return int hash code
|
||||
*/
|
||||
private int getAuthoritySetHashCode(Set<String> authorities)
|
||||
{
|
||||
@@ -514,10 +611,13 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
/**
|
||||
* Creates a new IPR group.
|
||||
*
|
||||
* @param groupNamePrefix group name prefix
|
||||
* @param children child authorities
|
||||
* @param index group index
|
||||
* @return String full name of created group
|
||||
* @param groupNamePrefix
|
||||
* group name prefix
|
||||
* @param children
|
||||
* child authorities
|
||||
* @param index
|
||||
* group index
|
||||
* @return String full name of created group
|
||||
*/
|
||||
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
|
||||
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.
|
||||
*
|
||||
* @param iprGroups iprGroups, first read and second write
|
||||
* @param nodeRef node reference
|
||||
* @param iprGroups
|
||||
* iprGroups, first read and second write
|
||||
* @param nodeRef
|
||||
* node reference
|
||||
*/
|
||||
private void assignIPRGroupsToNode(Pair<String, String> iprGroups, NodeRef nodeRef)
|
||||
{
|
||||
@@ -598,7 +700,8 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
/**
|
||||
* Clear the nodes IPR permissions
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
* @param nodeRef
|
||||
* node reference
|
||||
*/
|
||||
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)
|
||||
*/
|
||||
@Override @Deprecated public Set<String> getExtendedReaders(NodeRef nodeRef)
|
||||
@Override
|
||||
@Deprecated
|
||||
public Set<String> getExtendedReaders(NodeRef 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)
|
||||
*/
|
||||
@Override @Deprecated public Set<String> getExtendedWriters(NodeRef nodeRef)
|
||||
@Override
|
||||
@Deprecated
|
||||
public Set<String> getExtendedWriters(NodeRef 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)
|
||||
*/
|
||||
@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);
|
||||
}
|
||||
@@ -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)
|
||||
*/
|
||||
@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);
|
||||
}
|
||||
@@ -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)
|
||||
*/
|
||||
@Override @Deprecated public void removeAllExtendedSecurity(NodeRef nodeRef)
|
||||
@Override
|
||||
@Deprecated
|
||||
public void removeAllExtendedSecurity(NodeRef 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)
|
||||
*/
|
||||
@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);
|
||||
}
|
||||
@@ -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)
|
||||
*/
|
||||
@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);
|
||||
}
|
||||
@@ -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)
|
||||
*/
|
||||
@Override @Deprecated public void removeAllExtendedSecurity(NodeRef nodeRef, boolean applyToParents)
|
||||
@Override
|
||||
@Deprecated
|
||||
public void removeAllExtendedSecurity(NodeRef nodeRef, boolean applyToParents)
|
||||
{
|
||||
remove(nodeRef);
|
||||
}
|
||||
|
@@ -52,6 +52,7 @@ import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.model.RenditionModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
|
||||
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.NodeRef;
|
||||
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.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.AuthorityService;
|
||||
@@ -522,6 +524,104 @@ public class ExtendedSecurityServiceImplUnitTest
|
||||
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
|
||||
@@ -571,7 +671,7 @@ public class ExtendedSecurityServiceImplUnitTest
|
||||
.thenReturn(Stream
|
||||
.of(USER_W, AlfMock.generateText())
|
||||
.collect(Collectors.toSet()));
|
||||
|
||||
|
||||
// add extended security
|
||||
extendedSecurityService.set(nodeRef, READERS, WRITERS);
|
||||
|
||||
@@ -895,7 +995,7 @@ public class ExtendedSecurityServiceImplUnitTest
|
||||
// group names
|
||||
String readGroup = extendedSecurityService.getIPRGroupShortName(READER_GROUP_FULL_PREFIX, READERS, 0);
|
||||
String writeGroup = extendedSecurityService.getIPRGroupShortName(WRITER_GROUP_FULL_PREFIX, WRITERS, 0);
|
||||
|
||||
|
||||
// setup renditions
|
||||
NodeRef renditionNodeRef = AlfMock.generateNodeRef(mockedNodeService);
|
||||
when(mockedNodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_RECORD))
|
||||
@@ -904,7 +1004,7 @@ public class ExtendedSecurityServiceImplUnitTest
|
||||
.thenReturn(renditionNodeRef);
|
||||
when(mockedNodeService.getChildAssocs(nodeRef, RenditionModel.ASSOC_RENDITION, RegexQNamePattern.MATCH_ALL))
|
||||
.thenReturn(Collections.singletonList(mockedChildAssociationRef));
|
||||
|
||||
|
||||
// setup permissions
|
||||
Set<AccessPermission> permissions = Stream
|
||||
.of(new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, readGroup, 0),
|
||||
@@ -913,17 +1013,17 @@ public class ExtendedSecurityServiceImplUnitTest
|
||||
.collect(Collectors.toSet());
|
||||
when(mockedPermissionService.getAllSetPermissions(nodeRef))
|
||||
.thenReturn(permissions);
|
||||
|
||||
|
||||
// remove extended security
|
||||
extendedSecurityService.remove(nodeRef);
|
||||
|
||||
|
||||
// verify that the groups permissions have been removed
|
||||
verify(mockedPermissionService).clearPermission(nodeRef, readGroup);
|
||||
verify(mockedPermissionService).clearPermission(nodeRef, writeGroup);
|
||||
|
||||
|
||||
// verify that the groups permissions have been removed from the rendition
|
||||
verify(mockedPermissionService).clearPermission(renditionNodeRef, readGroup);
|
||||
verify(mockedPermissionService).clearPermission(renditionNodeRef, writeGroup);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||
<version>23.6.0.1</version>
|
||||
<version>23.6.0.14</version>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.6.0.1</version>
|
||||
<version>23.6.0.14</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||
<version>23.6.0.1</version>
|
||||
<version>23.6.0.14</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
@@ -51,8 +51,8 @@
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-lang</groupId>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
@@ -30,7 +30,7 @@ import java.util.regex.Pattern;
|
||||
|
||||
import org.alfresco.service.cmr.site.SiteInfo;
|
||||
import org.alfresco.service.cmr.wiki.WikiPageInfo;
|
||||
import org.apache.commons.lang.StringEscapeUtils;
|
||||
import org.apache.commons.lang3.StringEscapeUtils;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
@@ -92,7 +92,7 @@ public class WikiPageGet extends AbstractWikiWebScript
|
||||
{
|
||||
links.add(link);
|
||||
// build the list of available pages
|
||||
WikiPageInfo wikiPage = wikiService.getWikiPage(site.getShortName(), StringEscapeUtils.unescapeHtml(link));
|
||||
WikiPageInfo wikiPage = wikiService.getWikiPage(site.getShortName(), StringEscapeUtils.unescapeHtml4(link));
|
||||
if (wikiPage != null)
|
||||
{
|
||||
pageTitles.add(wikiPage.getTitle());
|
||||
|
@@ -45,7 +45,7 @@ import org.alfresco.service.cmr.wiki.WikiPageInfo;
|
||||
import org.alfresco.service.cmr.wiki.WikiService;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.PropertyMap;
|
||||
import org.apache.commons.lang.StringEscapeUtils;
|
||||
import org.apache.commons.lang3.StringEscapeUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.json.JSONArray;
|
||||
@@ -996,7 +996,7 @@ public class WikiRestApiTest extends BaseWebScriptTest
|
||||
String link = m.group(1);
|
||||
link += "?title=<script>alert('xss');</script>";
|
||||
WikiPageInfo wikiPage2 = this.wikiService.getWikiPage(SITE_SHORT_NAME_WIKI, link);
|
||||
WikiPageInfo wikiPage1 = this.wikiService.getWikiPage(SITE_SHORT_NAME_WIKI, StringEscapeUtils.unescapeHtml(link));
|
||||
WikiPageInfo wikiPage1 = this.wikiService.getWikiPage(SITE_SHORT_NAME_WIKI, StringEscapeUtils.unescapeHtml4(link));
|
||||
assertEquals(wikiPage2, wikiPage1);
|
||||
}
|
||||
|
||||
@@ -1006,4 +1006,4 @@ public class WikiRestApiTest extends BaseWebScriptTest
|
||||
this.wikiService.deleteWikiPage(wikiPageNew);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.6.0.1</version>
|
||||
<version>23.6.0.14</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.6.0.1</version>
|
||||
<version>23.6.0.14</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.6.0.1</version>
|
||||
<version>23.6.0.14</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -9,6 +9,6 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>23.6.0.1</version>
|
||||
<version>23.6.0.14</version>
|
||||
</parent>
|
||||
</project>
|
||||
|
@@ -36,8 +36,7 @@ commons-email http://jakarta.apache.org/commons/
|
||||
commons-fileupload http://jakarta.apache.org/commons/
|
||||
commons-httpclient http://jakarta.apache.org/commons/
|
||||
commons-io http://jakarta.apache.org/commons/
|
||||
commons-jxpath http://jakarta.apache.org/commons/
|
||||
commons-lang http://jakarta.apache.org/commons/
|
||||
commons-jxpath http://jakarta.apache.org/commons/
|
||||
commons-lang3 http://jakarta.apache.org/commons/
|
||||
commons-logging http://jakarta.apache.org/commons/
|
||||
commons-net http://jakarta.apache.org/commons/
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>23.6.0.1</version>
|
||||
<version>23.6.0.14</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.6.0.1</version>
|
||||
<version>23.6.0.14</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>23.6.0.1</version>
|
||||
<version>23.6.0.14</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>23.6.0.1</version>
|
||||
<version>23.6.0.14</version>
|
||||
</parent>
|
||||
|
||||
<organization>
|
||||
|
@@ -16,7 +16,7 @@ import org.alfresco.utility.testrail.annotation.TestRail;
|
||||
import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
|
||||
import org.apache.chemistry.opencmis.commons.exceptions.CmisPermissionDeniedException;
|
||||
import org.apache.chemistry.opencmis.commons.exceptions.CmisUnauthorizedException;
|
||||
import org.apache.commons.lang.time.DateUtils;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>23.6.0.1</version>
|
||||
<version>23.6.0.14</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>23.6.0.1</version>
|
||||
<version>23.6.0.14</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>23.6.0.1</version>
|
||||
<version>23.6.0.14</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
@@ -17,7 +17,7 @@
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<rest.api.explorer.branch>master</rest.api.explorer.branch>
|
||||
<httpclient-osgi-version>4.5.6</httpclient-osgi-version>
|
||||
<commons-lang3.version>3.17.0</commons-lang3.version>
|
||||
<commons-lang3.version>3.18.0</commons-lang3.version>
|
||||
<scribejava-apis.version>8.3.3</scribejava-apis.version>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -26,6 +26,13 @@
|
||||
package org.alfresco.rest.rules;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||
import static org.springframework.http.HttpStatus.CREATED;
|
||||
import static org.springframework.http.HttpStatus.FORBIDDEN;
|
||||
import static org.springframework.http.HttpStatus.NOT_FOUND;
|
||||
|
||||
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.ERROR_MESSAGE_ACCESS_RESTRICTED;
|
||||
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.MAIL_ACTION;
|
||||
import static org.alfresco.rest.rules.RulesTestsUtils.CHECKIN_ACTION;
|
||||
@@ -45,11 +52,6 @@ import static org.alfresco.utility.model.FileModel.getRandomFileModel;
|
||||
import static org.alfresco.utility.model.FileType.TEXT_PLAIN;
|
||||
import static org.alfresco.utility.model.UserModel.getRandomUserModel;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||
import static org.springframework.http.HttpStatus.CREATED;
|
||||
import static org.springframework.http.HttpStatus.FORBIDDEN;
|
||||
import static org.springframework.http.HttpStatus.NOT_FOUND;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
@@ -61,10 +63,13 @@ import java.util.stream.IntStream;
|
||||
import jakarta.json.Json;
|
||||
import jakarta.json.JsonObject;
|
||||
|
||||
import org.apache.chemistry.opencmis.client.api.CmisObject;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import org.alfresco.rest.model.RestActionBodyExecTemplateModel;
|
||||
import org.alfresco.rest.model.RestActionConstraintModel;
|
||||
import org.alfresco.rest.model.RestCompositeConditionDefinitionModel;
|
||||
import org.alfresco.rest.model.RestPaginationModel;
|
||||
import org.alfresco.rest.model.RestRuleModel;
|
||||
import org.alfresco.rest.model.RestRuleModelsCollection;
|
||||
import org.alfresco.utility.constants.UserRole;
|
||||
@@ -74,9 +79,6 @@ import org.alfresco.utility.model.FolderModel;
|
||||
import org.alfresco.utility.model.SiteModel;
|
||||
import org.alfresco.utility.model.TestGroup;
|
||||
import org.alfresco.utility.model.UserModel;
|
||||
import org.apache.chemistry.opencmis.client.api.CmisObject;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* Tests for POST /nodes/{nodeId}/rule-sets/{ruleSetId}/rules.
|
||||
@@ -101,13 +103,13 @@ public class CreateRulesTests extends RulesRestTest
|
||||
* <p>
|
||||
* Also check that the isShared field is not returned when not requested.
|
||||
*/
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY})
|
||||
public void createRule()
|
||||
{
|
||||
RestRuleModel ruleModel = rulesUtils.createRuleModelWithModifiedValues();
|
||||
|
||||
RestRuleModel rule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.createSingleRule(ruleModel);
|
||||
.createSingleRule(ruleModel);
|
||||
|
||||
RestRuleModel expectedRuleModel = rulesUtils.createRuleModelWithModifiedValues();
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
@@ -117,7 +119,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check creating a rule in a non-existent folder returns an error. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRuleInNonExistentFolder()
|
||||
{
|
||||
STEP("Try to create a rule in non-existent folder.");
|
||||
@@ -134,7 +136,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check creating a rule in a non-existent rule set returns an error. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRuleInNonExistentRuleSet()
|
||||
{
|
||||
STEP("Try to create a rule in non-existent rule set.");
|
||||
@@ -148,7 +150,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Try to create a rule without a name and check the error. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRuleWithEmptyName()
|
||||
{
|
||||
RestRuleModel ruleModel = rulesUtils.createRuleModel("");
|
||||
@@ -160,7 +162,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check we can create two rules with the same name. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void duplicateRuleNameIsAcceptable()
|
||||
{
|
||||
RestRuleModel ruleModel = rulesUtils.createRuleModel("duplicateRuleName");
|
||||
@@ -175,7 +177,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check that a user without permission to view the folder cannot create a rule in it. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void requireReadPermissionToCreateRule()
|
||||
{
|
||||
STEP("Create a user and use them to create a private site containing a folder");
|
||||
@@ -194,7 +196,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check that a Collaborator cannot create a rule in a folder in a private site. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void siteCollaboratorCannotCreateRule()
|
||||
{
|
||||
testRolePermissionsWith(SiteCollaborator);
|
||||
@@ -204,7 +206,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check that a Contributor cannot create a rule in a private folder. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void siteContributorCannotCreateRule()
|
||||
{
|
||||
testRolePermissionsWith(SiteContributor);
|
||||
@@ -214,7 +216,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check that a Consumer cannot create a rule in a folder in a private site. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void siteConsumerCannotCreateRule()
|
||||
{
|
||||
testRolePermissionsWith(SiteConsumer);
|
||||
@@ -224,7 +226,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check that a siteManager can create a rule in a folder in a private site. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void siteManagerCanCreateRule()
|
||||
{
|
||||
testRolePermissionsWith(SiteManager)
|
||||
@@ -234,7 +236,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check we can't create a rule under a document node. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void tryToCreateRuleUnderDocument()
|
||||
{
|
||||
STEP("Create a document.");
|
||||
@@ -250,7 +252,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check we can create several rules. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRules()
|
||||
{
|
||||
STEP("Create a list of rules in one POST request");
|
||||
@@ -258,19 +260,18 @@ public class CreateRulesTests extends RulesRestTest
|
||||
List<RestRuleModel> ruleModels = ruleNames.stream().map(rulesUtils::createRuleModel).collect(toList());
|
||||
|
||||
RestRuleModelsCollection rules = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.createListOfRules(ruleModels);
|
||||
.createListOfRules(ruleModels);
|
||||
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
|
||||
assertEquals("Unexpected number of rules received in response.", ruleNames.size(), rules.getEntries().size());
|
||||
IntStream.range(0, ruleModels.size()).forEach(i ->
|
||||
rules.getEntries().get(i).onModel()
|
||||
.assertThat().field("id").isNotNull()
|
||||
.assertThat().field("name").is(ruleNames.get(i)));
|
||||
IntStream.range(0, ruleModels.size()).forEach(i -> rules.getEntries().get(i).onModel()
|
||||
.assertThat().field("id").isNotNull()
|
||||
.assertThat().field("name").is(ruleNames.get(i)));
|
||||
}
|
||||
|
||||
/** Check we can create over 100 rules and get them all back in response. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createOver100Rules()
|
||||
{
|
||||
STEP("Create a list of 120 rules in one POST request");
|
||||
@@ -287,10 +288,9 @@ public class CreateRulesTests extends RulesRestTest
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
|
||||
assertEquals("Unexpected number of rules received in response.", ruleCount, rules.getEntries().size());
|
||||
IntStream.range(0, ruleModels.size()).forEach(i ->
|
||||
rules.getEntries().get(i).onModel()
|
||||
.assertThat().field("id").isNotNull()
|
||||
.assertThat().field("name").is(ruleNamePrefix + (i + 1)));
|
||||
IntStream.range(0, ruleModels.size()).forEach(i -> rules.getEntries().get(i).onModel()
|
||||
.assertThat().field("id").isNotNull()
|
||||
.assertThat().field("name").is(ruleNamePrefix + (i + 1)));
|
||||
|
||||
rules.getPagination()
|
||||
.assertThat().field("count").is(ruleCount)
|
||||
@@ -302,7 +302,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Try to create several rules with an error in one of them. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRulesWithOneError()
|
||||
{
|
||||
STEP("Try to create a three rules but the middle one has an error.");
|
||||
@@ -319,55 +319,55 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check we can create a rule without description. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRuleWithoutDescription()
|
||||
{
|
||||
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||
UserModel admin = dataUser.getAdminUser();
|
||||
|
||||
RestRuleModel rule = restClient.authenticateUser(admin).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.createSingleRule(ruleModel);
|
||||
.createSingleRule(ruleModel);
|
||||
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
rule.assertThat().field("id").isNotNull()
|
||||
.assertThat().field("name").is(RULE_NAME_DEFAULT)
|
||||
.assertThat().field("description").isNull();
|
||||
.assertThat().field("name").is(RULE_NAME_DEFAULT)
|
||||
.assertThat().field("description").isNull();
|
||||
}
|
||||
|
||||
/** Check we can create a rule without specifying triggers but with the default "inbound" value. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRuleWithoutTriggers()
|
||||
{
|
||||
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||
UserModel admin = dataUser.getAdminUser();
|
||||
|
||||
RestRuleModel rule = restClient.authenticateUser(admin).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.createSingleRule(ruleModel);
|
||||
.createSingleRule(ruleModel);
|
||||
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
rule.assertThat().field("id").isNotNull()
|
||||
.assertThat().field("name").is(RULE_NAME_DEFAULT)
|
||||
.assertThat().field("triggers").is(List.of("inbound"));
|
||||
.assertThat().field("name").is(RULE_NAME_DEFAULT)
|
||||
.assertThat().field("triggers").is(List.of("inbound"));
|
||||
}
|
||||
|
||||
/** Check we can create a rule without error script. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRuleWithoutErrorScript()
|
||||
{
|
||||
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||
UserModel admin = dataUser.getAdminUser();
|
||||
|
||||
RestRuleModel rule = restClient.authenticateUser(admin).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.createSingleRule(ruleModel);
|
||||
.createSingleRule(ruleModel);
|
||||
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
rule.assertThat().field("id").isNotNull()
|
||||
.assertThat().field("name").is(RULE_NAME_DEFAULT)
|
||||
.assertThat().field("errorScript").isNull();
|
||||
.assertThat().field("name").is(RULE_NAME_DEFAULT)
|
||||
.assertThat().field("errorScript").isNull();
|
||||
}
|
||||
|
||||
/** Check we can create a rule with irrelevant isShared flag, and it doesn't have impact to the process. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRuleWithSharedFlag()
|
||||
{
|
||||
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||
@@ -375,23 +375,23 @@ public class CreateRulesTests extends RulesRestTest
|
||||
UserModel admin = dataUser.getAdminUser();
|
||||
|
||||
RestRuleModel rule = restClient.authenticateUser(admin).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.createSingleRule(ruleModel);
|
||||
.createSingleRule(ruleModel);
|
||||
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
rule.assertThat().field("id").isNotNull()
|
||||
.assertThat().field("name").is(RULE_NAME_DEFAULT)
|
||||
.assertThat().field("isShared").isNull();
|
||||
.assertThat().field("name").is(RULE_NAME_DEFAULT)
|
||||
.assertThat().field("isShared").isNull();
|
||||
}
|
||||
|
||||
/** Check we can create a rule. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY})
|
||||
public void createRuleAndIncludeFieldsInResponse()
|
||||
{
|
||||
RestRuleModel ruleModel = rulesUtils.createRuleModel("ruleName");
|
||||
|
||||
RestRuleModel rule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.include("isShared")
|
||||
.createSingleRule(ruleModel);
|
||||
.include("isShared")
|
||||
.createSingleRule(ruleModel);
|
||||
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
rule.assertThat().field("isShared").isNotNull();
|
||||
@@ -412,7 +412,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check that the folder's owner can create rules, even if it is in a private site they aren't a member of. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void checkOwnerCanCreateRule()
|
||||
{
|
||||
STEP("Use admin to create a private site.");
|
||||
@@ -431,7 +431,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check that an administrator can create a rule in a private site even if they aren't a member. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void checkAdminCanCreateRule()
|
||||
{
|
||||
STEP("Use a user to create a private site with a folder.");
|
||||
@@ -446,7 +446,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check that a coordinator can create rules in folders outside sites. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void checkCoordinatorCanCreateRule()
|
||||
{
|
||||
STEP("Create a folder in the user's file space.");
|
||||
@@ -454,11 +454,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
|
||||
STEP("Create another user as a coordinator for this folder.");
|
||||
UserModel coordinator = dataUser.createRandomTestUser("Rules");
|
||||
/*
|
||||
Update folder node properties to add a coordinator
|
||||
{ "permissions": { "isInheritanceEnabled": true, "locallySet": { "authorityId": "coordinator.getUsername()",
|
||||
"name": "Coordinator", "accessStatus":"ALLOWED" } } }
|
||||
*/
|
||||
/* Update folder node properties to add a coordinator { "permissions": { "isInheritanceEnabled": true, "locallySet": { "authorityId": "coordinator.getUsername()", "name": "Coordinator", "accessStatus":"ALLOWED" } } } */
|
||||
String putBody = getAddPermissionsBody(coordinator.getUsername(), "Coordinator");
|
||||
restClient.authenticateUser(user).withCoreAPI().usingNode(folder).updateNode(putBody);
|
||||
|
||||
@@ -470,7 +466,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check that an editor cannot create rules in folders outside sites. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void checkEditorCannotCreateRule()
|
||||
{
|
||||
STEP("Create a folder in the user's file space.");
|
||||
@@ -478,11 +474,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
|
||||
STEP("Create another user as a editor for this folder.");
|
||||
UserModel editor = dataUser.createRandomTestUser();
|
||||
/*
|
||||
Update folder node properties to add an editor
|
||||
{ "permissions": { "isInheritanceEnabled": true, "locallySet": { "authorityId": "editor.getUsername()",
|
||||
"name": "Coordinator", "accessStatus":"ALLOWED" } } }
|
||||
*/
|
||||
/* Update folder node properties to add an editor { "permissions": { "isInheritanceEnabled": true, "locallySet": { "authorityId": "editor.getUsername()", "name": "Coordinator", "accessStatus":"ALLOWED" } } } */
|
||||
String putBody = getAddPermissionsBody(editor.getUsername(), "Editor");
|
||||
restClient.authenticateUser(user).withCoreAPI().usingNode(folder).updateNode(putBody);
|
||||
|
||||
@@ -494,7 +486,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check that a collaborator cannot create rules in folders outside sites. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void checkCollaboratorCannotCreateRule()
|
||||
{
|
||||
STEP("Create a folder in the user's file space.");
|
||||
@@ -502,11 +494,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
|
||||
STEP("Create another user as a collaborator for this folder.");
|
||||
UserModel collaborator = dataUser.createRandomTestUser();
|
||||
/*
|
||||
Update folder node properties to add a collaborator
|
||||
{ "permissions": { "isInheritanceEnabled": true, "locallySet": { "authorityId": "collaborator.getUsername()",
|
||||
"name": "Coordinator", "accessStatus":"ALLOWED" } } }
|
||||
*/
|
||||
/* Update folder node properties to add a collaborator { "permissions": { "isInheritanceEnabled": true, "locallySet": { "authorityId": "collaborator.getUsername()", "name": "Coordinator", "accessStatus":"ALLOWED" } } } */
|
||||
String putBody = getAddPermissionsBody(collaborator.getUsername(), "Collaborator");
|
||||
restClient.authenticateUser(user).withCoreAPI().usingNode(folder).updateNode(putBody);
|
||||
|
||||
@@ -572,10 +560,10 @@ public class CreateRulesTests extends RulesRestTest
|
||||
public void createRuleWithActions_userCannotUsePrivateAction()
|
||||
{
|
||||
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.createSingleRule(rulesUtils.createRuleWithPrivateAction());
|
||||
.createSingleRule(rulesUtils.createRuleWithPrivateAction());
|
||||
|
||||
restClient.assertStatusCodeIs(FORBIDDEN)
|
||||
.assertLastError().containsSummary(ERROR_MESSAGE_ACCESS_RESTRICTED);
|
||||
.assertLastError().containsSummary(ERROR_MESSAGE_ACCESS_RESTRICTED);
|
||||
}
|
||||
|
||||
/** Check that an administrator can create rules that use private actions. */
|
||||
@@ -583,7 +571,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
public void createRuleWithActions_adminCanUsePrivateAction()
|
||||
{
|
||||
restClient.authenticateUser(dataUser.getAdminUser()).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.createSingleRule(rulesUtils.createRuleWithPrivateAction());
|
||||
.createSingleRule(rulesUtils.createRuleWithPrivateAction());
|
||||
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
}
|
||||
@@ -656,8 +644,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
public void createRuleWithNotApplicableActionShouldFail()
|
||||
{
|
||||
final RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||
final RestActionBodyExecTemplateModel invalidAction =
|
||||
rulesUtils.createCustomActionModel(RulesTestsUtils.DELETE_RENDITION_ACTION, Map.of("dummy-key", "dummy-value"));
|
||||
final RestActionBodyExecTemplateModel invalidAction = rulesUtils.createCustomActionModel(RulesTestsUtils.DELETE_RENDITION_ACTION, Map.of("dummy-key", "dummy-value"));
|
||||
ruleModel.setActions(List.of(invalidAction));
|
||||
|
||||
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
|
||||
@@ -673,8 +660,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
public void createRuleWithMissingActionParametersShouldFail()
|
||||
{
|
||||
final RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||
final RestActionBodyExecTemplateModel invalidAction =
|
||||
rulesUtils.createCustomActionModel(RulesTestsUtils.COPY_ACTION, Collections.emptyMap());
|
||||
final RestActionBodyExecTemplateModel invalidAction = rulesUtils.createCustomActionModel(RulesTestsUtils.COPY_ACTION, Collections.emptyMap());
|
||||
ruleModel.setActions(List.of(invalidAction));
|
||||
|
||||
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
@@ -736,7 +722,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
public void createRuleWithoutMandatoryActionParametersShouldFail()
|
||||
{
|
||||
final RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||
final RestActionBodyExecTemplateModel invalidAction = rulesUtils.createCustomActionModel(COPY_ACTION, Map.of("deep-copy",false));
|
||||
final RestActionBodyExecTemplateModel invalidAction = rulesUtils.createCustomActionModel(COPY_ACTION, Map.of("deep-copy", false));
|
||||
ruleModel.setActions(List.of(invalidAction));
|
||||
|
||||
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
@@ -749,7 +735,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
/**
|
||||
* Check we get error when attempting to create a rule that copies files to a non-existent folder.
|
||||
*/
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRuleThatUsesNonExistentNode()
|
||||
{
|
||||
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||
@@ -758,16 +744,16 @@ public class CreateRulesTests extends RulesRestTest
|
||||
ruleModel.setActions(List.of(invalidAction));
|
||||
|
||||
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.createSingleRule(ruleModel);
|
||||
.createSingleRule(ruleModel);
|
||||
|
||||
restClient.assertStatusCodeIs(NOT_FOUND);
|
||||
restClient.assertLastError().containsSummary("The entity with id: non-existent-node was not found");
|
||||
restClient.assertLastError().containsSummary("Destination folder having Id: non-existent-node no longer exists. Please update your rule definition.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check we get error when attempting to create a rule that references a folder that the user does not have read permission for.
|
||||
*/
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRuleThatUsesNodeWithoutReadPermission()
|
||||
{
|
||||
SiteModel privateSite = dataSite.usingAdmin().createPrivateRandomSite();
|
||||
@@ -779,7 +765,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
ruleModel.setActions(List.of(invalidAction));
|
||||
|
||||
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.createSingleRule(ruleModel);
|
||||
.createSingleRule(ruleModel);
|
||||
|
||||
restClient.assertStatusCodeIs(NOT_FOUND);
|
||||
restClient.assertLastError().containsSummary("The entity with id: " + privateFolder.getNodeRef() + " was not found");
|
||||
@@ -788,7 +774,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
/**
|
||||
* Check we get error when attempting to create a rule that copies files to a folder that a user only has read permission for.
|
||||
*/
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRuleThatWritesToNodeWithoutPermission()
|
||||
{
|
||||
SiteModel privateSite = dataSite.usingAdmin().createPrivateRandomSite();
|
||||
@@ -802,7 +788,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
ruleModel.setActions(List.of(invalidAction));
|
||||
|
||||
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.createSingleRule(ruleModel);
|
||||
.createSingleRule(ruleModel);
|
||||
|
||||
restClient.assertStatusCodeIs(FORBIDDEN);
|
||||
restClient.assertLastError().containsSummary("No proper permissions for node: " + privateFolder.getNodeRef());
|
||||
@@ -828,7 +814,6 @@ public class CreateRulesTests extends RulesRestTest
|
||||
restClient.assertLastError().containsSummary("Node is not a folder " + fileModel.getNodeRef());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check we get error when attempting to create a rule with mail action defined with non-existing mail template.
|
||||
*/
|
||||
@@ -850,7 +835,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
ruleModel.setActions(List.of(mailAction));
|
||||
|
||||
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.createSingleRule(ruleModel);
|
||||
.createSingleRule(ruleModel);
|
||||
|
||||
restClient.assertStatusCodeIs(BAD_REQUEST);
|
||||
restClient.assertLastError().containsSummary("Action parameter: template has invalid value (" + mailTemplate +
|
||||
@@ -860,7 +845,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
/**
|
||||
* Check the user can create a rule with a script.
|
||||
*/
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void checkCanUseScriptInRule()
|
||||
{
|
||||
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||
@@ -869,7 +854,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
ruleModel.setActions(List.of(scriptAction));
|
||||
|
||||
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.createSingleRule(ruleModel);
|
||||
.createSingleRule(ruleModel);
|
||||
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
}
|
||||
@@ -877,7 +862,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
/**
|
||||
* Check the script has to be stored in the scripts directory in the data dictionary.
|
||||
*/
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void checkCantUseNodeOutsideScriptsDirectory()
|
||||
{
|
||||
STEP("Copy script to location outside data dictionary.");
|
||||
@@ -898,16 +883,16 @@ public class CreateRulesTests extends RulesRestTest
|
||||
ruleModel.setActions(List.of(scriptAction));
|
||||
|
||||
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.createSingleRule(ruleModel);
|
||||
.createSingleRule(ruleModel);
|
||||
|
||||
restClient.assertStatusCodeIs(BAD_REQUEST)
|
||||
.assertLastError().containsSummary("script-ref has invalid value");
|
||||
.assertLastError().containsSummary("script-ref has invalid value");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check a real category needs to be supplied when linking to a category.
|
||||
*/
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void checkLinkToCategoryNeedsRealCategory()
|
||||
{
|
||||
STEP("Attempt to link to a category with a folder node, rather than a category node.");
|
||||
@@ -918,7 +903,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
ruleModel.setActions(List.of(categoryAction));
|
||||
|
||||
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.createSingleRule(ruleModel);
|
||||
.createSingleRule(ruleModel);
|
||||
|
||||
restClient.assertStatusCodeIs(BAD_REQUEST);
|
||||
}
|
||||
@@ -933,7 +918,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
ruleModel.setConditions(rulesUtils.createVariousConditions());
|
||||
|
||||
RestRuleModel rule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.createSingleRule(ruleModel);
|
||||
.createSingleRule(ruleModel);
|
||||
|
||||
RestRuleModel expectedRuleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||
expectedRuleModel.setConditions(rulesUtils.createVariousConditions());
|
||||
@@ -952,7 +937,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
ruleModel.setConditions(rulesUtils.createCompositeCondition(null));
|
||||
|
||||
RestRuleModel rule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
.createSingleRule(ruleModel);
|
||||
.createSingleRule(ruleModel);
|
||||
|
||||
RestRuleModel expectedRuleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||
expectedRuleModel.setTriggers(List.of("inbound"));
|
||||
@@ -969,10 +954,8 @@ public class CreateRulesTests extends RulesRestTest
|
||||
STEP("Try to create a rule with non existing category in conditions.");
|
||||
String fakeCategoryId = "bdba5f9f-fake-id22-803b-349bcfd06fd1";
|
||||
RestCompositeConditionDefinitionModel conditions = rulesUtils.createCompositeCondition(List.of(
|
||||
rulesUtils.createCompositeCondition(!INVERTED, List.of(
|
||||
rulesUtils.createSimpleCondition("category", "equals", fakeCategoryId)
|
||||
))
|
||||
));
|
||||
rulesUtils.createCompositeCondition(!INVERTED, List.of(
|
||||
rulesUtils.createSimpleCondition("category", "equals", fakeCategoryId)))));
|
||||
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||
ruleModel.setConditions(conditions);
|
||||
|
||||
@@ -992,9 +975,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
final String comparator = "greaterthan";
|
||||
RestCompositeConditionDefinitionModel conditions = rulesUtils.createCompositeCondition(List.of(
|
||||
rulesUtils.createCompositeCondition(!INVERTED, List.of(
|
||||
rulesUtils.createSimpleCondition("size", comparator, "500")
|
||||
))
|
||||
));
|
||||
rulesUtils.createSimpleCondition("size", comparator, "500")))));
|
||||
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||
ruleModel.setConditions(conditions);
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>23.6.0.1</version>
|
||||
<version>23.6.0.14</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>23.6.0.1</version>
|
||||
<version>23.6.0.14</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
22
pom.xml
22
pom.xml
@@ -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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.6.0.1</version>
|
||||
<version>23.6.0.14</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>Alfresco Community Repo Parent</name>
|
||||
|
||||
@@ -57,13 +57,13 @@
|
||||
<dependency.acs-event-model.version>0.0.33</dependency.acs-event-model.version>
|
||||
|
||||
<dependency.aspectj.version>1.9.22.1</dependency.aspectj.version>
|
||||
<dependency.spring.version>6.1.14</dependency.spring.version>
|
||||
<dependency.spring-security.version>6.3.8</dependency.spring-security.version>
|
||||
<dependency.spring.version>6.2.8</dependency.spring.version>
|
||||
<dependency.spring-security.version>6.3.9</dependency.spring-security.version>
|
||||
<dependency.antlr.version>3.5.3</dependency.antlr.version>
|
||||
<dependency.jackson.version>2.17.2</dependency.jackson.version>
|
||||
<dependency.cxf.version>4.1.0</dependency.cxf.version>
|
||||
<dependency.opencmis.version>1.0.0-jakarta-1</dependency.opencmis.version>
|
||||
<dependency.webscripts.version>9.4</dependency.webscripts.version>
|
||||
<dependency.webscripts.version>10.2</dependency.webscripts.version>
|
||||
<dependency.bouncycastle.version>1.78.1</dependency.bouncycastle.version>
|
||||
<dependency.mockito-core.version>5.14.1</dependency.mockito-core.version>
|
||||
<dependency.assertj.version>3.26.3</dependency.assertj.version>
|
||||
@@ -154,7 +154,7 @@
|
||||
<connection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</connection>
|
||||
<developerConnection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</developerConnection>
|
||||
<url>https://github.com/Alfresco/alfresco-community-repo</url>
|
||||
<tag>23.6.0.1</tag>
|
||||
<tag>23.6.0.14</tag>
|
||||
</scm>
|
||||
|
||||
<distributionManagement>
|
||||
@@ -409,7 +409,7 @@
|
||||
<dependency>
|
||||
<groupId>commons-beanutils</groupId>
|
||||
<artifactId>commons-beanutils</artifactId>
|
||||
<version>1.9.4</version>
|
||||
<version>1.11.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
@@ -417,9 +417,9 @@
|
||||
<version>1.17.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-lang</groupId>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
<version>2.6</version>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.18.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
@@ -439,8 +439,8 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-fileupload2-jakarta</artifactId>
|
||||
<version>2.0.0-M1</version>
|
||||
<artifactId>commons-fileupload2-jakarta-servlet6</artifactId>
|
||||
<version>2.0.0-M4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-net</groupId>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.6.0.1</version>
|
||||
<version>23.6.0.14</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -28,11 +28,9 @@ package org.alfresco.repo.web.scripts.transfer;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.alfresco.service.cmr.transfer.TransferException;
|
||||
import org.alfresco.service.cmr.transfer.TransferReceiver;
|
||||
import org.apache.commons.fileupload2.core.FileItemInput;
|
||||
import org.apache.commons.fileupload2.core.FileItemInputIterator;
|
||||
import org.apache.commons.fileupload2.jakarta.JakartaServletFileUpload;
|
||||
import org.apache.commons.fileupload2.jakarta.servlet6.JakartaServletFileUpload;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
@@ -41,6 +39,9 @@ import org.springframework.extensions.webscripts.WebScriptResponse;
|
||||
import org.springframework.extensions.webscripts.WrappingWebScriptRequest;
|
||||
import org.springframework.extensions.webscripts.servlet.WebScriptServletRequest;
|
||||
|
||||
import org.alfresco.service.cmr.transfer.TransferException;
|
||||
import org.alfresco.service.cmr.transfer.TransferReceiver;
|
||||
|
||||
/**
|
||||
* This command processor is used to receive one or more content files for a given transfer.
|
||||
*
|
||||
@@ -50,9 +51,9 @@ import org.springframework.extensions.webscripts.servlet.WebScriptServletRequest
|
||||
public class PostContentCommandProcessor implements CommandProcessor
|
||||
{
|
||||
private TransferReceiver receiver;
|
||||
|
||||
|
||||
private static final String MSG_CAUGHT_UNEXPECTED_EXCEPTION = "transfer_service.receiver.caught_unexpected_exception";
|
||||
|
||||
|
||||
private static Log logger = LogFactory.getLog(PostContentCommandProcessor.class);
|
||||
|
||||
/**
|
||||
@@ -64,12 +65,9 @@ public class PostContentCommandProcessor implements CommandProcessor
|
||||
this.receiver = receiver;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
/* (non-Javadoc)
|
||||
*
|
||||
* @see org.alfresco.repo.web.scripts.transfer.CommandProcessor#process(org.alfresco.web.scripts.WebScriptRequest,
|
||||
* org.alfresco.web.scripts.WebScriptResponse)
|
||||
*/
|
||||
* @see org.alfresco.repo.web.scripts.transfer.CommandProcessor#process(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse) */
|
||||
public int process(WebScriptRequest req, WebScriptResponse resp)
|
||||
{
|
||||
logger.debug("post content start");
|
||||
@@ -91,8 +89,7 @@ public class PostContentCommandProcessor implements CommandProcessor
|
||||
{
|
||||
current = null;
|
||||
}
|
||||
}
|
||||
while (current != null);
|
||||
} while (current != null);
|
||||
if (webScriptServletRequest == null)
|
||||
{
|
||||
resp.setStatus(Status.STATUS_BAD_REQUEST);
|
||||
@@ -101,7 +98,7 @@ public class PostContentCommandProcessor implements CommandProcessor
|
||||
|
||||
HttpServletRequest servletRequest = webScriptServletRequest.getHttpServletRequest();
|
||||
|
||||
//Read the transfer id from the request
|
||||
// Read the transfer id from the request
|
||||
String transferId = servletRequest.getParameter("transferId");
|
||||
|
||||
if ((transferId == null) || !JakartaServletFileUpload.isMultipartContent(servletRequest))
|
||||
@@ -124,34 +121,34 @@ public class PostContentCommandProcessor implements CommandProcessor
|
||||
logger.debug("got content Mime Part : " + name);
|
||||
receiver.saveContent(transferId, item.getName(), item.getInputStream());
|
||||
}
|
||||
}
|
||||
|
||||
// WebScriptServletRequest alfRequest = (WebScriptServletRequest)req;
|
||||
// String[] names = alfRequest.getParameterNames();
|
||||
// for(String name : names)
|
||||
// {
|
||||
// FormField item = alfRequest.getFileField(name);
|
||||
//
|
||||
// if(item != null)
|
||||
// {
|
||||
// logger.debug("got content Mime Part : " + name);
|
||||
// receiver.saveContent(transferId, item.getName(), item.getInputStream());
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// //TODO - should this be an exception?
|
||||
// logger.debug("Unable to get content for Mime Part : " + name);
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
// WebScriptServletRequest alfRequest = (WebScriptServletRequest)req;
|
||||
// String[] names = alfRequest.getParameterNames();
|
||||
// for(String name : names)
|
||||
// {
|
||||
// FormField item = alfRequest.getFileField(name);
|
||||
//
|
||||
// if(item != null)
|
||||
// {
|
||||
// logger.debug("got content Mime Part : " + name);
|
||||
// receiver.saveContent(transferId, item.getName(), item.getInputStream());
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// //TODO - should this be an exception?
|
||||
// logger.debug("Unable to get content for Mime Part : " + name);
|
||||
// }
|
||||
// }
|
||||
|
||||
logger.debug("success");
|
||||
|
||||
|
||||
resp.setStatus(Status.STATUS_OK);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.debug("exception caught", ex);
|
||||
if(transferId != null)
|
||||
if (transferId != null)
|
||||
{
|
||||
logger.debug("ending transfer", ex);
|
||||
receiver.end(transferId);
|
||||
|
@@ -27,15 +27,11 @@
|
||||
package org.alfresco.repo.web.scripts.transfer;
|
||||
|
||||
import java.io.OutputStream;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.alfresco.repo.transfer.TransferCommons;
|
||||
import org.alfresco.service.cmr.transfer.TransferException;
|
||||
import org.alfresco.service.cmr.transfer.TransferReceiver;
|
||||
import org.apache.commons.fileupload2.core.FileItemInput;
|
||||
import org.apache.commons.fileupload2.core.FileItemInputIterator;
|
||||
import org.apache.commons.fileupload2.jakarta.JakartaServletFileUpload;
|
||||
import org.apache.commons.fileupload2.jakarta.servlet6.JakartaServletFileUpload;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
@@ -44,6 +40,10 @@ import org.springframework.extensions.webscripts.WebScriptResponse;
|
||||
import org.springframework.extensions.webscripts.WrappingWebScriptRequest;
|
||||
import org.springframework.extensions.webscripts.servlet.WebScriptServletRequest;
|
||||
|
||||
import org.alfresco.repo.transfer.TransferCommons;
|
||||
import org.alfresco.service.cmr.transfer.TransferException;
|
||||
import org.alfresco.service.cmr.transfer.TransferReceiver;
|
||||
|
||||
/**
|
||||
* This command processor is used to receive the snapshot for a given transfer.
|
||||
*
|
||||
@@ -53,17 +53,17 @@ import org.springframework.extensions.webscripts.servlet.WebScriptServletRequest
|
||||
public class PostSnapshotCommandProcessor implements CommandProcessor
|
||||
{
|
||||
private TransferReceiver receiver;
|
||||
|
||||
|
||||
private static Log logger = LogFactory.getLog(PostSnapshotCommandProcessor.class);
|
||||
|
||||
private static final String MSG_CAUGHT_UNEXPECTED_EXCEPTION = "transfer_service.receiver.caught_unexpected_exception";
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.web.scripts.transfer.CommandProcessor#process(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
|
||||
*/
|
||||
*
|
||||
* @see org.alfresco.repo.web.scripts.transfer.CommandProcessor#process(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse) */
|
||||
public int process(WebScriptRequest req, WebScriptResponse resp)
|
||||
{
|
||||
|
||||
|
||||
int result = Status.STATUS_OK;
|
||||
// Unwrap to a WebScriptServletRequest if we have one
|
||||
WebScriptServletRequest webScriptServletRequest = null;
|
||||
@@ -83,45 +83,44 @@ public class PostSnapshotCommandProcessor implements CommandProcessor
|
||||
{
|
||||
current = null;
|
||||
}
|
||||
}
|
||||
while (current != null);
|
||||
if (webScriptServletRequest == null)
|
||||
} while (current != null);
|
||||
if (webScriptServletRequest == null)
|
||||
{
|
||||
logger.debug("bad request, not assignable from");
|
||||
resp.setStatus(Status.STATUS_BAD_REQUEST);
|
||||
return Status.STATUS_BAD_REQUEST;
|
||||
}
|
||||
|
||||
//We can't use the WebScriptRequest version of getParameter, since that may cause the content stream
|
||||
//to be parsed. Get hold of the raw HttpServletRequest and work with that.
|
||||
|
||||
// We can't use the WebScriptRequest version of getParameter, since that may cause the content stream
|
||||
// to be parsed. Get hold of the raw HttpServletRequest and work with that.
|
||||
HttpServletRequest servletRequest = webScriptServletRequest.getHttpServletRequest();
|
||||
|
||||
//Read the transfer id from the request
|
||||
|
||||
// Read the transfer id from the request
|
||||
String transferId = servletRequest.getParameter("transferId");
|
||||
|
||||
|
||||
if ((transferId == null) || !JakartaServletFileUpload.isMultipartContent(servletRequest))
|
||||
{
|
||||
logger.debug("bad request, not multipart");
|
||||
resp.setStatus(Status.STATUS_BAD_REQUEST);
|
||||
return Status.STATUS_BAD_REQUEST;
|
||||
}
|
||||
|
||||
try
|
||||
|
||||
try
|
||||
{
|
||||
logger.debug("about to upload manifest file");
|
||||
|
||||
JakartaServletFileUpload upload = new JakartaServletFileUpload();
|
||||
FileItemInputIterator iter = upload.getItemIterator(servletRequest);
|
||||
while (iter.hasNext())
|
||||
while (iter.hasNext())
|
||||
{
|
||||
FileItemInput item = iter.next();
|
||||
if (!item.isFormField() && TransferCommons.PART_NAME_MANIFEST.equals(item.getFieldName()))
|
||||
if (!item.isFormField() && TransferCommons.PART_NAME_MANIFEST.equals(item.getFieldName()))
|
||||
{
|
||||
logger.debug("got manifest file");
|
||||
receiver.saveSnapshot(transferId, item.getInputStream());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
logger.debug("success");
|
||||
resp.setStatus(Status.STATUS_OK);
|
||||
|
||||
@@ -133,10 +132,10 @@ public class PostSnapshotCommandProcessor implements CommandProcessor
|
||||
receiver.generateRequsite(transferId, out);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.debug("exception caught", ex);
|
||||
if(transferId != null)
|
||||
if (transferId != null)
|
||||
{
|
||||
logger.debug("ending transfer", ex);
|
||||
receiver.end(transferId);
|
||||
@@ -151,7 +150,8 @@ public class PostSnapshotCommandProcessor implements CommandProcessor
|
||||
}
|
||||
|
||||
/**
|
||||
* @param receiver the receiver to set
|
||||
* @param receiver
|
||||
* the receiver to set
|
||||
*/
|
||||
public void setReceiver(TransferReceiver receiver)
|
||||
{
|
||||
|
@@ -2,23 +2,23 @@
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
@@ -38,11 +38,19 @@ import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.repo.site.SiteModel;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.People;
|
||||
@@ -77,8 +85,6 @@ import org.alfresco.util.AlfrescoCollator;
|
||||
import org.alfresco.util.ISO9075;
|
||||
import org.alfresco.util.ParameterCheck;
|
||||
import org.alfresco.util.SearchLanguageConversion;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
|
||||
/**
|
||||
* Queries implementation
|
||||
@@ -88,43 +94,43 @@ import org.springframework.extensions.surf.util.I18NUtil;
|
||||
*/
|
||||
public class QueriesImpl implements Queries, InitializingBean
|
||||
{
|
||||
private final static Map<String,QName> NODE_SORT_PARAMS_TO_QNAMES = sortParamsToQNames(
|
||||
PARAM_NAME, ContentModel.PROP_NAME,
|
||||
PARAM_CREATEDAT, ContentModel.PROP_CREATED,
|
||||
PARAM_MODIFIEDAT, ContentModel.PROP_MODIFIED);
|
||||
private static final Log LOGGER = LogFactory.getLog(QueriesImpl.class);
|
||||
private final static Map<String, QName> NODE_SORT_PARAMS_TO_QNAMES = sortParamsToQNames(
|
||||
PARAM_NAME, ContentModel.PROP_NAME,
|
||||
PARAM_CREATEDAT, ContentModel.PROP_CREATED,
|
||||
PARAM_MODIFIEDAT, ContentModel.PROP_MODIFIED);
|
||||
|
||||
private final static Map<String, QName> PEOPLE_SORT_PARAMS_TO_QNAMES = sortParamsToQNames(
|
||||
PARAM_PERSON_ID, ContentModel.PROP_USERNAME,
|
||||
ContentModel.PROP_FIRSTNAME,
|
||||
ContentModel.PROP_LASTNAME);
|
||||
PARAM_PERSON_ID, ContentModel.PROP_USERNAME,
|
||||
ContentModel.PROP_FIRSTNAME,
|
||||
ContentModel.PROP_LASTNAME);
|
||||
|
||||
private final static Map<String, QName> SITE_SORT_PARAMS_TO_QNAMES = sortParamsToQNames(
|
||||
PARAM_SITE_ID, ContentModel.PROP_NAME,
|
||||
PARAM_SITE_TITLE, ContentModel.PROP_TITLE,
|
||||
PARAM_SITE_ID, ContentModel.PROP_NAME,
|
||||
PARAM_SITE_TITLE, ContentModel.PROP_TITLE,
|
||||
PARAM_SITE_DESCRIPTION, ContentModel.PROP_DESCRIPTION);
|
||||
|
||||
/**
|
||||
* Helper method to build a map of sort parameter names to QNames. This method iterates through
|
||||
* the parameters. If a parameter is a String it is assumed to be a sort parameter name and will
|
||||
* be followed by a QName to which it maps. If however it is a QName the local name of the OName
|
||||
* is used as the sort parameter name.
|
||||
* @param parameters to build up the map.
|
||||
* Helper method to build a map of sort parameter names to QNames. This method iterates through the parameters. If a parameter is a String it is assumed to be a sort parameter name and will be followed by a QName to which it maps. If however it is a QName the local name of the OName is used as the sort parameter name.
|
||||
*
|
||||
* @param parameters
|
||||
* to build up the map.
|
||||
* @return the map
|
||||
*/
|
||||
private static Map<String, QName> sortParamsToQNames(Object... parameters)
|
||||
{
|
||||
Map<String, QName> map = new HashMap<>();
|
||||
for (int i=0; i<parameters.length; i++)
|
||||
for (int i = 0; i < parameters.length; i++)
|
||||
{
|
||||
map.put(
|
||||
parameters[i] instanceof String
|
||||
? (String)parameters[i++]
|
||||
: ((QName)parameters[i]).getLocalName(),
|
||||
(QName)parameters[i]);
|
||||
parameters[i] instanceof String
|
||||
? (String) parameters[i++]
|
||||
: ((QName) parameters[i]).getLocalName(),
|
||||
(QName) parameters[i]);
|
||||
}
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
|
||||
private ServiceRegistry sr;
|
||||
private NodeService nodeService;
|
||||
private NamespaceService namespaceService;
|
||||
@@ -162,7 +168,7 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
ParameterCheck.mandatory("nodes", this.nodes);
|
||||
ParameterCheck.mandatory("people", this.people);
|
||||
ParameterCheck.mandatory("sites", this.sites);
|
||||
|
||||
|
||||
this.nodeService = sr.getNodeService();
|
||||
this.namespaceService = sr.getNamespaceService();
|
||||
this.dictionaryService = sr.getDictionaryService();
|
||||
@@ -173,10 +179,9 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
public CollectionWithPagingInfo<Node> findNodes(Parameters parameters)
|
||||
{
|
||||
SearchService searchService = sr.getSearchService();
|
||||
return new AbstractQuery<Node>(nodeService, searchService)
|
||||
{
|
||||
return new AbstractQuery<Node>(nodeService, searchService) {
|
||||
private final Map<String, UserInfo> mapUserInfo = new HashMap<>(10);
|
||||
|
||||
|
||||
@Override
|
||||
protected void buildQuery(StringBuilder query, String term, SearchParameters sp, String queryTemplateName)
|
||||
{
|
||||
@@ -198,14 +203,14 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
{
|
||||
query.append(")");
|
||||
}
|
||||
|
||||
|
||||
String nodeTypeStr = parameters.getParameter(PARAM_NODE_TYPE);
|
||||
if (nodeTypeStr != null)
|
||||
{
|
||||
QName filterNodeTypeQName = nodes.createQName(nodeTypeStr);
|
||||
if (dictionaryService.getType(filterNodeTypeQName) == null)
|
||||
{
|
||||
throw new InvalidArgumentException("Unknown filter nodeType: "+nodeTypeStr);
|
||||
throw new InvalidArgumentException("Unknown filter nodeType: " + nodeTypeStr);
|
||||
}
|
||||
|
||||
query.append(" AND (+TYPE:\"").append(nodeTypeStr).append(("\")"));
|
||||
@@ -229,7 +234,7 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
Path path = null;
|
||||
try
|
||||
{
|
||||
path = nodeService.getPath(nodeRef);
|
||||
path = nodeService.getPath(nodeRef);
|
||||
}
|
||||
catch (InvalidNodeRefException inre)
|
||||
{
|
||||
@@ -248,7 +253,7 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
{
|
||||
// first request for this namespace prefix, get and cache result
|
||||
Collection<String> prefixes = namespaceService.getPrefixes(qname.getNamespaceURI());
|
||||
prefix = prefixes.size() != 0 ? prefixes.iterator().next() : "";
|
||||
prefix = !prefixes.isEmpty() ? prefixes.iterator().next() : "";
|
||||
cache.put(qname.getNamespaceURI(), prefix);
|
||||
}
|
||||
buf.append('/').append(prefix).append(':').append(ISO9075.encode(qname.getLocalName()));
|
||||
@@ -262,12 +267,6 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Node> newList(int capacity)
|
||||
{
|
||||
return new ArrayList<Node>(capacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node convert(NodeRef nodeRef, List<String> includeParam)
|
||||
{
|
||||
@@ -281,18 +280,17 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
term = SearchLanguageConversion.escapeLuceneQuery(term);
|
||||
return term;
|
||||
}
|
||||
|
||||
|
||||
}.find(parameters, PARAM_TERM, MIN_TERM_LENGTH_NODES, "keywords",
|
||||
IN_QUERY_SORT, NODE_SORT_PARAMS_TO_QNAMES,
|
||||
new SortColumn(PARAM_MODIFIEDAT, false));
|
||||
IN_QUERY_SORT, NODE_SORT_PARAMS_TO_QNAMES,
|
||||
new SortColumn(PARAM_MODIFIEDAT, false));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CollectionWithPagingInfo<Person> findPeople(Parameters parameters)
|
||||
{
|
||||
SearchService searchService = sr.getSearchService();
|
||||
return new AbstractQuery<Person>(nodeService, searchService)
|
||||
{
|
||||
return new AbstractQuery<Person>(nodeService, searchService) {
|
||||
@Override
|
||||
protected void buildQuery(StringBuilder query, String term, SearchParameters sp, String queryTemplateName)
|
||||
{
|
||||
@@ -305,33 +303,25 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
query.append("*\")");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Person> newList(int capacity)
|
||||
{
|
||||
return new ArrayList<Person>(capacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Person convert(NodeRef nodeRef, List<String> includeParam)
|
||||
{
|
||||
String personId = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_USERNAME);
|
||||
Person person = people.getPerson(personId);
|
||||
return person;
|
||||
return people.getPerson(personId);
|
||||
}
|
||||
|
||||
|
||||
// TODO Do the sort in the query on day. A comment in the code for the V0 API used for live people
|
||||
// search says adding sort values for this query don't work - tried it and they really don't.
|
||||
// search says adding sort values for this query don't work - tried it and they really don't.
|
||||
}.find(parameters, PARAM_TERM, MIN_TERM_LENGTH_PEOPLE, "_PERSON",
|
||||
POST_QUERY_SORT, PEOPLE_SORT_PARAMS_TO_QNAMES,
|
||||
new SortColumn(PARAM_FIRSTNAME, true), new SortColumn(PARAM_LASTNAME, true));
|
||||
POST_QUERY_SORT, PEOPLE_SORT_PARAMS_TO_QNAMES,
|
||||
new SortColumn(PARAM_FIRSTNAME, true), new SortColumn(PARAM_LASTNAME, true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionWithPagingInfo<Site> findSites(Parameters parameters)
|
||||
{
|
||||
SearchService searchService = sr.getSearchService();
|
||||
return new AbstractQuery<Site>(nodeService, searchService)
|
||||
{
|
||||
return new AbstractQuery<Site>(nodeService, searchService) {
|
||||
@Override
|
||||
protected void buildQuery(StringBuilder query, String term, SearchParameters sp, String queryTemplateName)
|
||||
{
|
||||
@@ -343,44 +333,34 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
query.append(term);
|
||||
query.append("*\")");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Site> newList(int capacity)
|
||||
{
|
||||
return new ArrayList<>(capacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Site convert(NodeRef nodeRef, List<String> includeParam)
|
||||
{
|
||||
return getSite(siteService.getSite(nodeRef), true);
|
||||
return getSite(siteService.getSite(nodeRef));
|
||||
}
|
||||
|
||||
// note: see also Sites.getSite
|
||||
private Site getSite(SiteInfo siteInfo, boolean includeRole)
|
||||
private Site getSite(SiteInfo siteInfo)
|
||||
{
|
||||
// set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url)
|
||||
String siteId = siteInfo.getShortName();
|
||||
String role = null;
|
||||
if(includeRole)
|
||||
{
|
||||
role = sites.getSiteRole(siteId);
|
||||
}
|
||||
String role = sites.getSiteRole(siteId);
|
||||
return new Site(siteInfo, role);
|
||||
}
|
||||
}.find(parameters, PARAM_TERM, MIN_TERM_LENGTH_SITES, "_SITE", POST_QUERY_SORT, SITE_SORT_PARAMS_TO_QNAMES, new SortColumn(PARAM_SITE_TITLE, true));
|
||||
}
|
||||
|
||||
|
||||
public abstract static class AbstractQuery<T>
|
||||
{
|
||||
public enum Sort
|
||||
{
|
||||
IN_QUERY_SORT, POST_QUERY_SORT
|
||||
}
|
||||
|
||||
|
||||
private final NodeService nodeService;
|
||||
private final SearchService searchService;
|
||||
|
||||
|
||||
public AbstractQuery(NodeService nodeService, SearchService searchService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
@@ -388,14 +368,14 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
}
|
||||
|
||||
public CollectionWithPagingInfo<T> find(Parameters parameters,
|
||||
String termName, int minTermLength, String queryTemplateName,
|
||||
Sort sort, Map<String, QName> sortParamsToQNames, SortColumn... defaultSort)
|
||||
String termName, int minTermLength, String queryTemplateName,
|
||||
Sort sort, Map<String, QName> sortParamsToQNames, SortColumn... defaultSort)
|
||||
{
|
||||
SearchParameters sp = new SearchParameters();
|
||||
sp.setLanguage(SearchService.LANGUAGE_FTS_ALFRESCO);
|
||||
sp.addStore(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE);
|
||||
sp.setDefaultFieldName(queryTemplateName);
|
||||
|
||||
|
||||
String term = getTerm(parameters, termName, minTermLength);
|
||||
|
||||
StringBuilder query = new StringBuilder();
|
||||
@@ -404,7 +384,7 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
|
||||
Paging paging = parameters.getPaging();
|
||||
PagingRequest pagingRequest = Util.getPagingRequest(paging);
|
||||
|
||||
|
||||
List<SortColumn> defaultSortCols = (defaultSort != null ? Arrays.asList(defaultSort) : Collections.emptyList());
|
||||
if (sort == IN_QUERY_SORT)
|
||||
{
|
||||
@@ -413,36 +393,43 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
sp.setSkipCount(pagingRequest.getSkipCount());
|
||||
sp.setMaxItems(pagingRequest.getMaxItems());
|
||||
}
|
||||
|
||||
|
||||
ResultSet queryResults = null;
|
||||
List<T> collection = null;
|
||||
try
|
||||
{
|
||||
queryResults = searchService.query(sp);
|
||||
|
||||
|
||||
List<NodeRef> nodeRefs = queryResults.getNodeRefs();
|
||||
|
||||
if (sort == POST_QUERY_SORT)
|
||||
{
|
||||
nodeRefs = postQuerySort(parameters, sortParamsToQNames, defaultSortCols, nodeRefs);
|
||||
}
|
||||
|
||||
collection = newList(nodeRefs.size());
|
||||
|
||||
Map<NodeRef, T>
|
||||
|
||||
collection = new LinkedHashMap<>(nodeRefs.size());
|
||||
List<String> includeParam = parameters.getInclude();
|
||||
|
||||
for (NodeRef nodeRef : nodeRefs)
|
||||
{
|
||||
T t = convert(nodeRef, includeParam);
|
||||
collection.add(t);
|
||||
try
|
||||
{
|
||||
T t = convert(nodeRef, includeParam);
|
||||
collection.put(nodeRef, t);
|
||||
}
|
||||
catch (AccessDeniedException ade)
|
||||
{
|
||||
LOGGER.debug("Ignoring search result for nodeRef " + nodeRef + " due to access denied exception", ade);
|
||||
}
|
||||
}
|
||||
|
||||
if (sort == POST_QUERY_SORT)
|
||||
{
|
||||
return listPage(collection, paging);
|
||||
List<T> postQuerySortedCollection = postQuerySort(parameters, sortParamsToQNames, defaultSortCols, collection.keySet())
|
||||
.stream()
|
||||
.map(collection::get)
|
||||
.toList();
|
||||
return listPage(postQuerySortedCollection, paging);
|
||||
}
|
||||
else
|
||||
{
|
||||
return CollectionWithPagingInfo.asPaged(paging, collection, queryResults.hasMore(), Long.valueOf(queryResults.getNumberFound()).intValue());
|
||||
return CollectionWithPagingInfo.asPaged(paging, collection.values(), queryResults.hasMore(), Long.valueOf(queryResults.getNumberFound()).intValue());
|
||||
}
|
||||
}
|
||||
finally
|
||||
@@ -455,40 +442,39 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds up the query and is expected to call {@link SearchParameters#setDefaultFieldName(String)}
|
||||
* and {@link SearchParameters#addQueryTemplate(String, String)}
|
||||
* @param query StringBuilder into which the query should be built.
|
||||
* @param term to be searched for
|
||||
* @param sp SearchParameters
|
||||
* Builds up the query and is expected to call {@link SearchParameters#setDefaultFieldName(String)} and {@link SearchParameters#addQueryTemplate(String, String)}
|
||||
*
|
||||
* @param query
|
||||
* StringBuilder into which the query should be built.
|
||||
* @param term
|
||||
* to be searched for
|
||||
* @param sp
|
||||
* SearchParameters
|
||||
* @param queryTemplateName
|
||||
*/
|
||||
protected abstract void buildQuery(StringBuilder query, String term, SearchParameters sp, String queryTemplateName);
|
||||
|
||||
/**
|
||||
* Returns a list of the correct type.
|
||||
* @param capacity of the list
|
||||
* @return a new list.
|
||||
*/
|
||||
protected abstract List<T> newList(int capacity);
|
||||
|
||||
/**
|
||||
* Converts a nodeRef into the an object of the required type.
|
||||
* @param nodeRef to be converted
|
||||
* @param includeParam additional fields to be included
|
||||
*
|
||||
* @param nodeRef
|
||||
* to be converted
|
||||
* @param includeParam
|
||||
* additional fields to be included
|
||||
* @return the object
|
||||
*/
|
||||
protected abstract T convert(NodeRef nodeRef, List<String> includeParam);
|
||||
|
||||
|
||||
protected String getTerm(Parameters parameters, String termName, int minTermLength)
|
||||
{
|
||||
String term = parameters.getParameter(termName);
|
||||
if (term == null)
|
||||
{
|
||||
throw new InvalidArgumentException("Query '"+termName+"' not specified");
|
||||
throw new InvalidArgumentException("Query '" + termName + "' not specified");
|
||||
}
|
||||
|
||||
|
||||
term = escapeTerm(term);
|
||||
|
||||
|
||||
int cnt = 0;
|
||||
for (int i = 0; i < term.length(); i++)
|
||||
{
|
||||
@@ -505,7 +491,7 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
|
||||
if (cnt < minTermLength)
|
||||
{
|
||||
throw new InvalidArgumentException("Query '"+termName+"' is too short. Must have at least "+minTermLength+" alphanumeric chars");
|
||||
throw new InvalidArgumentException("Query '" + termName + "' is too short. Must have at least " + minTermLength + " alphanumeric chars");
|
||||
}
|
||||
|
||||
return term;
|
||||
@@ -524,12 +510,12 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
term = SearchLanguageConversion.escapeLuceneQuery(term);
|
||||
return term;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds sort order to the SearchParameters.
|
||||
*/
|
||||
protected void addSortOrder(Parameters parameters, Map<String, QName> sortParamsToQNames,
|
||||
List<SortColumn> defaultSortCols, SearchParameters sp)
|
||||
List<SortColumn> defaultSortCols, SearchParameters sp)
|
||||
{
|
||||
List<SortColumn> sortCols = getSorting(parameters, defaultSortCols);
|
||||
for (SortColumn sortCol : sortCols)
|
||||
@@ -537,16 +523,16 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
QName sortPropQName = sortParamsToQNames.get(sortCol.column);
|
||||
if (sortPropQName == null)
|
||||
{
|
||||
throw new InvalidArgumentException("Invalid sort field: "+sortCol.column);
|
||||
throw new InvalidArgumentException("Invalid sort field: " + sortCol.column);
|
||||
}
|
||||
sp.addSort("@" + sortPropQName, sortCol.asc);
|
||||
sp.addSort("@" + sortPropQName, sortCol.asc);
|
||||
}
|
||||
}
|
||||
|
||||
private List<SortColumn> getSorting(Parameters parameters, List<SortColumn> defaultSortCols)
|
||||
{
|
||||
List<SortColumn> sortCols = parameters.getSorting();
|
||||
if (sortCols == null || sortCols.size() == 0)
|
||||
if (sortCols == null || sortCols.isEmpty())
|
||||
{
|
||||
sortCols = defaultSortCols == null ? Collections.emptyList() : defaultSortCols;
|
||||
}
|
||||
@@ -554,63 +540,66 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
}
|
||||
|
||||
protected List<NodeRef> postQuerySort(Parameters parameters, Map<String, QName> sortParamsToQNames,
|
||||
List<SortColumn> defaultSortCols, List<NodeRef> nodeRefs)
|
||||
List<SortColumn> defaultSortCols, Set<NodeRef> unsortedNodeRefs)
|
||||
{
|
||||
final List<SortColumn> sortCols = getSorting(parameters, defaultSortCols);
|
||||
int sortColCount = sortCols.size();
|
||||
if (sortColCount > 0)
|
||||
{
|
||||
// make copy of nodeRefs because it can be unmodifiable list.
|
||||
nodeRefs = new ArrayList<NodeRef>(nodeRefs);
|
||||
|
||||
List<QName> sortPropQNames = new ArrayList<>(sortColCount);
|
||||
for (SortColumn sortCol : sortCols)
|
||||
{
|
||||
QName sortPropQName = sortParamsToQNames.get(sortCol.column);
|
||||
if (sortPropQName == null)
|
||||
{
|
||||
throw new InvalidArgumentException("Invalid sort field: "+sortCol.column);
|
||||
}
|
||||
sortPropQNames.add(sortPropQName);
|
||||
}
|
||||
|
||||
final Collator col = AlfrescoCollator.getInstance(I18NUtil.getLocale());
|
||||
Collections.sort(nodeRefs, new Comparator<NodeRef>()
|
||||
{
|
||||
@Override
|
||||
public int compare(NodeRef n1, NodeRef n2)
|
||||
{
|
||||
int result = 0;
|
||||
for (int i=0; i<sortCols.size(); i++)
|
||||
{
|
||||
SortColumn sortCol = sortCols.get(i);
|
||||
QName sortPropQName = sortPropQNames.get(i);
|
||||
|
||||
Serializable p1 = getProperty(n1, sortPropQName);
|
||||
Serializable p2 = getProperty(n2, sortPropQName);
|
||||
|
||||
result = ((p1 instanceof Long) && (p2 instanceof Long)
|
||||
? Long.compare((Long)p1, (Long)p2)
|
||||
if (sortColCount == 0)
|
||||
{
|
||||
return new ArrayList<>(unsortedNodeRefs);
|
||||
}
|
||||
|
||||
// make copy of nodeRefs because it can be unmodifiable list.
|
||||
List<NodeRef> sortedNodeRefs = new ArrayList<>(unsortedNodeRefs);
|
||||
|
||||
List<QName> sortPropQNames = new ArrayList<>(sortColCount);
|
||||
for (SortColumn sortCol : sortCols)
|
||||
{
|
||||
QName sortPropQName = sortParamsToQNames.get(sortCol.column);
|
||||
if (sortPropQName == null)
|
||||
{
|
||||
throw new InvalidArgumentException("Invalid sort field: " + sortCol.column);
|
||||
}
|
||||
sortPropQNames.add(sortPropQName);
|
||||
}
|
||||
|
||||
final Collator col = AlfrescoCollator.getInstance(I18NUtil.getLocale());
|
||||
Collections.sort(sortedNodeRefs, new Comparator<NodeRef>() {
|
||||
@Override
|
||||
public int compare(NodeRef n1, NodeRef n2)
|
||||
{
|
||||
int result = 0;
|
||||
for (int i = 0; i < sortCols.size(); i++)
|
||||
{
|
||||
SortColumn sortCol = sortCols.get(i);
|
||||
QName sortPropQName = sortPropQNames.get(i);
|
||||
|
||||
Serializable p1 = getProperty(n1, sortPropQName);
|
||||
Serializable p2 = getProperty(n2, sortPropQName);
|
||||
|
||||
result = ((p1 instanceof Long) && (p2 instanceof Long)
|
||||
? Long.compare((Long) p1, (Long) p2)
|
||||
: col.compare(p1.toString(), p2.toString()))
|
||||
* (sortCol.asc ? 1 : -1);
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Serializable getProperty(NodeRef nodeRef, QName sortPropQName)
|
||||
{
|
||||
Serializable result = nodeService.getProperty(nodeRef, sortPropQName);
|
||||
return result == null ? "" : result;
|
||||
}
|
||||
private Serializable getProperty(NodeRef nodeRef, QName sortPropQName)
|
||||
{
|
||||
Serializable result = nodeService.getProperty(nodeRef, sortPropQName);
|
||||
return result == null ? "" : result;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
return nodeRefs;
|
||||
});
|
||||
|
||||
return sortedNodeRefs;
|
||||
}
|
||||
|
||||
// note: see also AbstractNodeRelation
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -39,6 +39,9 @@ import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.logging.log4j.util.Strings;
|
||||
|
||||
import org.alfresco.repo.action.executer.CheckOutActionExecuter;
|
||||
import org.alfresco.repo.action.executer.CopyActionExecuter;
|
||||
import org.alfresco.repo.action.executer.ImageTransformActionExecuter;
|
||||
@@ -58,8 +61,6 @@ import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.logging.log4j.util.Strings;
|
||||
|
||||
/**
|
||||
* This class provides logic for validation of permissions for action parameters which reference node.
|
||||
@@ -67,15 +68,14 @@ import org.apache.logging.log4j.util.Strings;
|
||||
public class ActionNodeParameterValidator implements ActionValidator
|
||||
{
|
||||
/**
|
||||
* This list holds action parameter names which require only READ permission on a referenced node
|
||||
* That means, all other parameters that reference nodes will require WRITE permission
|
||||
* This list holds action parameter names which require only READ permission on a referenced node That means, all other parameters that reference nodes will require WRITE permission
|
||||
*/
|
||||
static final Map<String, List<String>> REQUIRE_READ_PERMISSION_PARAMS =
|
||||
Map.of(LinkCategoryActionExecuter.NAME, List.of(LinkCategoryActionExecuter.PARAM_CATEGORY_VALUE));
|
||||
static final Map<String, List<String>> REQUIRE_READ_PERMISSION_PARAMS = Map.of(LinkCategoryActionExecuter.NAME, List.of(LinkCategoryActionExecuter.PARAM_CATEGORY_VALUE));
|
||||
|
||||
static final String NO_PROPER_PERMISSIONS_FOR_NODE = "No proper permissions for node: ";
|
||||
static final String NOT_A_CATEGORY = "Node is not a category ";
|
||||
static final String NOT_A_FOLDER = "Node is not a folder ";
|
||||
static final String NO_LONGER_EXISTS = "%s having Id: %s no longer exists. Please update your rule definition.";
|
||||
|
||||
private final Actions actions;
|
||||
private final NamespaceService namespaceService;
|
||||
@@ -83,7 +83,7 @@ public class ActionNodeParameterValidator implements ActionValidator
|
||||
private final PermissionService permissionService;
|
||||
|
||||
public ActionNodeParameterValidator(Actions actions, NamespaceService namespaceService, Nodes nodes,
|
||||
PermissionService permissionService)
|
||||
PermissionService permissionService)
|
||||
{
|
||||
this.actions = actions;
|
||||
this.namespaceService = namespaceService;
|
||||
@@ -94,7 +94,8 @@ public class ActionNodeParameterValidator implements ActionValidator
|
||||
/**
|
||||
* Validates action parameters that reference nodes against access permissions for executing user.
|
||||
*
|
||||
* @param action Action to be validated
|
||||
* @param action
|
||||
* Action to be validated
|
||||
*/
|
||||
@Override
|
||||
public void validate(Action action)
|
||||
@@ -124,7 +125,7 @@ public class ActionNodeParameterValidator implements ActionValidator
|
||||
}
|
||||
|
||||
private void validateNodes(final List<ActionDefinition.ParameterDefinition> nodeRefParamDefinitions,
|
||||
final Action action)
|
||||
final Action action)
|
||||
{
|
||||
if (MapUtils.isNotEmpty(action.getParams()))
|
||||
{
|
||||
@@ -132,7 +133,15 @@ public class ActionNodeParameterValidator implements ActionValidator
|
||||
.filter(pd -> action.getParams().containsKey(pd.getName()))
|
||||
.forEach(p -> {
|
||||
final String nodeId = Objects.toString(action.getParams().get(p.getName()), Strings.EMPTY);
|
||||
final NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
NodeRef nodeRef;
|
||||
try
|
||||
{
|
||||
nodeRef = nodes.validateNode(nodeId);
|
||||
}
|
||||
catch (EntityNotFoundException e)
|
||||
{
|
||||
throw new EntityNotFoundException(String.format(NO_LONGER_EXISTS, p.getDisplayLabel(), nodeId), e);
|
||||
}
|
||||
validatePermission(action.getActionDefinitionId(), p.getName(), nodeRef);
|
||||
validateType(action.getActionDefinitionId(), nodeRef);
|
||||
});
|
||||
@@ -163,7 +172,8 @@ public class ActionNodeParameterValidator implements ActionValidator
|
||||
{
|
||||
throw new InvalidArgumentException(NOT_A_FOLDER + nodeRef.getId());
|
||||
}
|
||||
} else if (!nodes.nodeMatches(nodeRef, Set.of(TYPE_CATEGORY), Collections.emptySet()))
|
||||
}
|
||||
else if (!nodes.nodeMatches(nodeRef, Set.of(TYPE_CATEGORY), Collections.emptySet()))
|
||||
{
|
||||
throw new InvalidArgumentException(NOT_A_CATEGORY + nodeRef.getId());
|
||||
}
|
||||
|
@@ -25,6 +25,20 @@
|
||||
*/
|
||||
package org.alfresco.rest.api.tests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.rest.AbstractSingleNetworkSiteTest;
|
||||
import org.alfresco.rest.api.Queries;
|
||||
@@ -36,27 +50,12 @@ import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.search.SearchParameters;
|
||||
import org.alfresco.service.cmr.site.SiteService;
|
||||
import org.alfresco.service.cmr.site.SiteVisibility;
|
||||
import org.alfresco.util.testing.category.LuceneTests;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.experimental.categories.Category;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* V1 REST API tests for pre-defined 'live' search Queries on Sites
|
||||
* V1 REST API tests for pre-defined 'live' search Queries on Sites
|
||||
*
|
||||
* <ul>
|
||||
* <li> {@literal <host>:<port>/alfresco/api/<networkId>/public/alfresco/versions/1/queries/sites} </li>
|
||||
* <li>{@literal <host>:<port>/alfresco/api/<networkId>/public/alfresco/versions/1/queries/sites}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author janv
|
||||
@@ -64,7 +63,7 @@ import static org.mockito.Mockito.verify;
|
||||
public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest
|
||||
{
|
||||
private static final String URL_QUERIES_LSS = "queries/sites";
|
||||
|
||||
|
||||
private SiteService siteService;
|
||||
|
||||
@Before
|
||||
@@ -72,7 +71,7 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest
|
||||
public void setup() throws Exception
|
||||
{
|
||||
super.setup();
|
||||
siteService = (SiteService)applicationContext.getBean("SiteService");
|
||||
siteService = (SiteService) applicationContext.getBean("SiteService");
|
||||
}
|
||||
|
||||
// Note expectedIds defaults to ids
|
||||
@@ -86,7 +85,7 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest
|
||||
}
|
||||
|
||||
dummySearchServiceQueryNodeRefs.clear();
|
||||
for (String id: ids)
|
||||
for (String id : ids)
|
||||
{
|
||||
NodeRef nodeRef = getNodeRef(id);
|
||||
dummySearchServiceQueryNodeRefs.add(nodeRef);
|
||||
@@ -98,7 +97,7 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest
|
||||
if (expectedStatus == 200)
|
||||
{
|
||||
String termWithEscapedAsterisks = term.replaceAll("\\*", "\\\\*");
|
||||
String expectedQuery = "TYPE:\"{http://www.alfresco.org/model/site/1.0}site\" AND (\"*"+ termWithEscapedAsterisks +"*\")";
|
||||
String expectedQuery = "TYPE:\"{http://www.alfresco.org/model/site/1.0}site\" AND (\"*" + termWithEscapedAsterisks + "*\")";
|
||||
ArgumentCaptor<SearchParameters> searchParametersCaptor = ArgumentCaptor.forClass(SearchParameters.class);
|
||||
verify(mockSearchService, times(++callCountToMockSearchService)).query(searchParametersCaptor.capture());
|
||||
SearchParameters parameters = searchParametersCaptor.getValue();
|
||||
@@ -109,30 +108,32 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest
|
||||
|
||||
if (orderBy != null)
|
||||
{
|
||||
for (int i=0; i<expectedIds.length; i++)
|
||||
for (int i = 0; i < expectedIds.length; i++)
|
||||
{
|
||||
String id = expectedIds[i];
|
||||
String actualId = sites.get(i).getId();
|
||||
assertEquals("Order "+i+":", id, actualId);
|
||||
assertEquals("Order " + i + ":", id, actualId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Tests basic api for nodes live search sites - metadata (id, title, description)
|
||||
*
|
||||
* <p>GET:</p>
|
||||
* <p>
|
||||
* GET:
|
||||
* </p>
|
||||
* {@literal <host>:<port>/alfresco/api/<networkId>/public/alfresco/versions/1/queries/sites}
|
||||
*/
|
||||
@Test
|
||||
public void testLiveSearchSites() throws Exception
|
||||
{
|
||||
setRequestContext(user1);
|
||||
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(user1);
|
||||
int sCount = 5;
|
||||
assertTrue(sCount > 4); // as relied on by test below
|
||||
|
||||
|
||||
List<String> siteIds = new ArrayList<>(sCount);
|
||||
|
||||
try
|
||||
@@ -149,14 +150,14 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest
|
||||
String siteD = "siteD";
|
||||
|
||||
int charValue = siteI.charAt(0);
|
||||
|
||||
|
||||
// create some some sites with site id: ab00001, abc00002, abcd00003, abcde00004, abcdef00005 (and some specific titles and descriptions)
|
||||
for (int i = 1; i <= sCount; i++)
|
||||
{
|
||||
String num = String.format("%05d", i);
|
||||
|
||||
charValue = charValue+1;
|
||||
siteI = siteI + String.valueOf((char)charValue);
|
||||
charValue = charValue + 1;
|
||||
siteI = siteI + String.valueOf((char) charValue);
|
||||
|
||||
String siteId = siteI + num + RUNID;
|
||||
String siteTitle = siteT + num + siteT;
|
||||
@@ -220,7 +221,7 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest
|
||||
{
|
||||
// some cleanup
|
||||
setRequestContext(user1);
|
||||
|
||||
|
||||
for (String siteId : siteIds)
|
||||
{
|
||||
deleteSite(siteId, true, 204);
|
||||
@@ -230,14 +231,20 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest
|
||||
|
||||
private NodeRef getNodeRef(String createdSiteId)
|
||||
{
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(user1);
|
||||
// Created sites do not return NodeRefs to the caller so we need to get the NodeRef from the siteService.
|
||||
// Temporarily as admin we will get NodeRefs to handle ACL authorization.
|
||||
String userUnderTest = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(DEFAULT_ADMIN);
|
||||
|
||||
// The following call to siteService.getSite(createdSiteId).getNodeRef() returns a NodeRef like:
|
||||
// workspace://SpacesStore/9db76769-96de-4de4-bdb4-a127130af362
|
||||
// workspace://SpacesStore/9db76769-96de-4de4-bdb4-a127130af362
|
||||
// We call tenantService.getName(nodeRef) to get a fully qualified NodeRef as Solr returns this.
|
||||
// They look like:
|
||||
// workspace://@org.alfresco.rest.api.tests.queriespeopleapitest@SpacesStore/9db76769-96de-4de4-bdb4-a127130af362
|
||||
// workspace://@org.alfresco.rest.api.tests.queriespeopleapitest@SpacesStore/9db76769-96de-4de4-bdb4-a127130af362
|
||||
NodeRef nodeRef = siteService.getSite(createdSiteId).getNodeRef();
|
||||
nodeRef = tenantService.getName(nodeRef);
|
||||
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(userUnderTest);
|
||||
return nodeRef;
|
||||
}
|
||||
|
||||
@@ -245,7 +252,7 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest
|
||||
public void testLiveSearchSites_SortPage() throws Exception
|
||||
{
|
||||
setRequestContext(user1);
|
||||
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(user1);
|
||||
List<String> siteIds = new ArrayList<>(5);
|
||||
|
||||
try
|
||||
@@ -253,14 +260,14 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest
|
||||
// As user 1 ...
|
||||
|
||||
Paging paging = getPaging(0, 100);
|
||||
|
||||
|
||||
// create site
|
||||
String s1 = createSite("siABCDEF"+RUNID, "ABCDEF DEF", "sdABCDEF", SiteVisibility.PRIVATE, 201).getId();
|
||||
String s2 = createSite("siABCD"+RUNID, "ABCD DEF", "sdABCD", SiteVisibility.PRIVATE, 201).getId();
|
||||
String s3 = createSite("siABCDE"+RUNID, "ABCDE DEF", "sdABCDE", SiteVisibility.PRIVATE, 201).getId();
|
||||
String s4 = createSite("siAB"+RUNID, "AB DEF", "sdAB", SiteVisibility.PRIVATE, 201).getId();
|
||||
String s5 = createSite("siABC"+RUNID, "ABC DEF", "sdABC", SiteVisibility.PRIVATE, 201).getId();
|
||||
|
||||
String s1 = createSite("siABCDEF" + RUNID, "ABCDEF DEF", "sdABCDEF", SiteVisibility.PRIVATE, 201).getId();
|
||||
String s2 = createSite("siABCD" + RUNID, "ABCD DEF", "sdABCD", SiteVisibility.PRIVATE, 201).getId();
|
||||
String s3 = createSite("siABCDE" + RUNID, "ABCDE DEF", "sdABCDE", SiteVisibility.PRIVATE, 201).getId();
|
||||
String s4 = createSite("siAB" + RUNID, "AB DEF", "sdAB", SiteVisibility.PRIVATE, 201).getId();
|
||||
String s5 = createSite("siABC" + RUNID, "ABC DEF", "sdABC", SiteVisibility.PRIVATE, 201).getId();
|
||||
|
||||
// test sort order
|
||||
{
|
||||
// default sort order - title asc
|
||||
@@ -276,11 +283,11 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest
|
||||
// basic paging tests
|
||||
{
|
||||
// sort order - title desc
|
||||
checkApiCall("siAB", "title desc", getPaging(0, 2), 200, new String[] {s1, s3}, s1, s3, s2, s5, s4);
|
||||
checkApiCall("siAB", "title desc", getPaging(2, 2), 200, new String[] {s2, s5}, s1, s3, s2, s5, s4);
|
||||
checkApiCall("siAB", "title desc", getPaging(4, 2), 200, new String[] {s4}, s1, s3, s2, s5, s4);
|
||||
checkApiCall("siAB", "title desc", getPaging(0, 2), 200, new String[]{s1, s3}, s1, s3, s2, s5, s4);
|
||||
checkApiCall("siAB", "title desc", getPaging(2, 2), 200, new String[]{s2, s5}, s1, s3, s2, s5, s4);
|
||||
checkApiCall("siAB", "title desc", getPaging(4, 2), 200, new String[]{s4}, s1, s3, s2, s5, s4);
|
||||
}
|
||||
|
||||
|
||||
// -ve tests
|
||||
{
|
||||
// -ve test - invalid sort field
|
||||
@@ -304,7 +311,52 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If the search service do not support ACL filtering, then the Queries API should handle the response to exclude private sites and potential unauthorized error when building response.
|
||||
*/
|
||||
@Test
|
||||
public void testLiveSearchExcludesPrivateSites() throws Exception
|
||||
{
|
||||
String publicSiteId = null;
|
||||
String privateSiteId = null;
|
||||
try
|
||||
{
|
||||
// given
|
||||
setRequestContext(null, DEFAULT_ADMIN, DEFAULT_ADMIN_PWD);
|
||||
createUser("bartender");
|
||||
|
||||
publicSiteId = createSite("samePrefixPublicSite", "samePrefixPublicSite", "Visible to all users", SiteVisibility.PUBLIC, 201).getId();
|
||||
privateSiteId = createSite("samePrefixPrivateSite", "samePrefixPrivateSite", "Hidden from bartender", SiteVisibility.PRIVATE, 201).getId();
|
||||
|
||||
String[] searchResults = {publicSiteId, privateSiteId};
|
||||
String[] expectedSites = {publicSiteId};
|
||||
|
||||
// when
|
||||
setRequestContext(null, "bartender", "password");
|
||||
AuthenticationUtil.setFullyAuthenticatedUser("bartender");
|
||||
|
||||
// then
|
||||
checkApiCall("samePrefix", null, getPaging(0, 100), 200, expectedSites, searchResults);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// cleanup
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(DEFAULT_ADMIN);
|
||||
setRequestContext(null, DEFAULT_ADMIN, DEFAULT_ADMIN_PWD);
|
||||
if (publicSiteId != null)
|
||||
{
|
||||
deleteSite(publicSiteId, true, 204);
|
||||
}
|
||||
if (privateSiteId != null)
|
||||
{
|
||||
deleteSite(privateSiteId, true, 204);
|
||||
}
|
||||
deleteUser("bartender", null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getScope()
|
||||
{
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.6.0.1</version>
|
||||
<version>23.6.0.14</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
@@ -85,7 +85,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-fileupload2-jakarta</artifactId>
|
||||
<artifactId>commons-fileupload2-jakarta-servlet6</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
@@ -94,7 +94,6 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.17.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
@@ -742,10 +741,6 @@
|
||||
<artifactId>reflections</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-lang</groupId>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -125,6 +125,9 @@ public class RhinoScriptProcessor extends BaseProcessor implements ScriptProcess
|
||||
/** Number of (bytecode) instructions that will trigger the observer */
|
||||
private int observerInstructionCount = 100;
|
||||
|
||||
/** Flag to enable or disable scope cleaning at the end of each script execution */
|
||||
private boolean cleanScope = true;
|
||||
|
||||
/** Custom context factory */
|
||||
public static AlfrescoContextFactory contextFactory;
|
||||
|
||||
@@ -209,6 +212,15 @@ public class RhinoScriptProcessor extends BaseProcessor implements ScriptProcess
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cleanScope
|
||||
* true to enable scope cleaning at the end of each script execution - set to false to disable this feature.
|
||||
*/
|
||||
public void setCleanScope(boolean cleanScope)
|
||||
{
|
||||
this.cleanScope = cleanScope;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.service.cmr.repository.ScriptProcessor#reset()
|
||||
*/
|
||||
public void reset()
|
||||
@@ -614,7 +626,7 @@ public class RhinoScriptProcessor extends BaseProcessor implements ScriptProcess
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!secure)
|
||||
if (!secure && cleanScope)
|
||||
{
|
||||
unsetScope(model, scope);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -81,11 +81,19 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea
|
||||
|
||||
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 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 int SOURCE_HAS_NO_CONTENT = -1;
|
||||
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);
|
||||
|
||||
// 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
|
||||
{
|
||||
if (!isEnabled())
|
||||
if (!isAsyncAllowed(renderOrTransform))
|
||||
{
|
||||
throw new RenditionService2Exception("Async transforms and renditions are disabled " +
|
||||
"(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);
|
||||
}
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -30,6 +30,9 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.cache.lookup.EntityLookupCache;
|
||||
import org.alfresco.repo.domain.node.Node;
|
||||
@@ -41,8 +44,6 @@ import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.EqualsHelper;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
public class NodePermissionAssessor
|
||||
{
|
||||
@@ -57,7 +58,7 @@ public class NodePermissionAssessor
|
||||
private long startTime;
|
||||
private int maxPermissionChecks;
|
||||
private long maxPermissionCheckTimeMillis;
|
||||
|
||||
|
||||
private EntityLookupCache<Long, Node, NodeRef> nodesCache;
|
||||
private NodeService nodeService;
|
||||
private PermissionService permissionService;
|
||||
@@ -68,7 +69,7 @@ public class NodePermissionAssessor
|
||||
this.permissionService = permissionService;
|
||||
this.nodesCache = nodeCache;
|
||||
this.nodeService = nodeService;
|
||||
|
||||
|
||||
this.checksPerformed = 0;
|
||||
this.maxPermissionChecks = Integer.MAX_VALUE;
|
||||
this.maxPermissionCheckTimeMillis = Long.MAX_VALUE;
|
||||
@@ -82,12 +83,12 @@ public class NodePermissionAssessor
|
||||
}
|
||||
|
||||
public boolean isIncluded(Node node)
|
||||
{
|
||||
{
|
||||
if (isFirstRecord())
|
||||
{
|
||||
this.startTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
|
||||
checksPerformed++;
|
||||
return isReallyIncluded(node);
|
||||
}
|
||||
@@ -107,34 +108,34 @@ public class NodePermissionAssessor
|
||||
String owner = getOwner(node);
|
||||
return EqualsHelper.nullSafeEquals(authority.getAuthority(), owner);
|
||||
}
|
||||
|
||||
|
||||
private String getOwner(Node node)
|
||||
{
|
||||
nodesCache.setValue(node.getId(), node);
|
||||
Set<QName> nodeAspects = nodeService.getAspects(node.getNodeRef());
|
||||
|
||||
|
||||
String userName = null;
|
||||
if (nodeAspects.contains(ContentModel.ASPECT_AUDITABLE))
|
||||
{
|
||||
userName = node.getAuditableProperties().getAuditCreator();
|
||||
}
|
||||
else if (nodeAspects.contains(ContentModel.ASPECT_OWNABLE))
|
||||
if (nodeAspects.contains(ContentModel.ASPECT_OWNABLE))
|
||||
{
|
||||
Serializable owner = nodeService.getProperty(node.getNodeRef(), ContentModel.PROP_OWNER);
|
||||
userName = DefaultTypeConverter.INSTANCE.convert(String.class, owner);
|
||||
}
|
||||
|
||||
else if (nodeAspects.contains(ContentModel.ASPECT_AUDITABLE))
|
||||
{
|
||||
userName = node.getAuditableProperties().getAuditCreator();
|
||||
}
|
||||
|
||||
return userName;
|
||||
}
|
||||
|
||||
|
||||
boolean isReallyIncluded(Node node)
|
||||
{
|
||||
if (isNullReading)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return isSystemReading ||
|
||||
|
||||
return isSystemReading ||
|
||||
isAdminReading ||
|
||||
canRead(node.getAclId()) ||
|
||||
isOwnerReading(node, authority);
|
||||
@@ -151,7 +152,7 @@ public class NodePermissionAssessor
|
||||
this.maxPermissionChecks = maxPermissionChecks + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean shouldQuitChecks()
|
||||
{
|
||||
if (checksPerformed >= maxPermissionChecks)
|
||||
@@ -173,7 +174,7 @@ public class NodePermissionAssessor
|
||||
{
|
||||
this.maxPermissionCheckTimeMillis = maxPermissionCheckTimeMillis;
|
||||
}
|
||||
|
||||
|
||||
protected boolean canRead(Long aclId)
|
||||
{
|
||||
Boolean res = aclReadCache.get(aclId);
|
||||
@@ -184,7 +185,7 @@ public class NodePermissionAssessor
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
protected boolean canCurrentUserRead(Long aclId)
|
||||
{
|
||||
// cache resolved ACLs
|
||||
@@ -195,7 +196,7 @@ public class NodePermissionAssessor
|
||||
{
|
||||
if (authorities.contains(auth))
|
||||
{
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,10 +205,10 @@ public class NodePermissionAssessor
|
||||
{
|
||||
if (authorities.contains(auth))
|
||||
{
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -74,7 +74,7 @@ import com.nimbusds.oauth2.sdk.id.Identifier;
|
||||
import com.nimbusds.oauth2.sdk.id.Issuer;
|
||||
import com.nimbusds.openid.connect.sdk.claims.PersonClaims;
|
||||
import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.hc.client5.http.classic.HttpClient;
|
||||
|
@@ -42,7 +42,7 @@ import jakarta.servlet.http.HttpServletResponse;
|
||||
import com.nimbusds.oauth2.sdk.Scope;
|
||||
import com.nimbusds.oauth2.sdk.id.Identifier;
|
||||
import com.nimbusds.oauth2.sdk.id.State;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -28,9 +28,6 @@ package org.alfresco.repo.transaction;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
@@ -38,6 +35,10 @@ import org.springframework.transaction.TransactionManager;
|
||||
import org.springframework.transaction.interceptor.TransactionAspectSupport;
|
||||
import org.springframework.transaction.interceptor.TransactionAttribute;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
|
||||
/**
|
||||
* @author Dmitry Velichkevich
|
||||
*/
|
||||
@@ -64,7 +65,7 @@ public class RetryingTransactionInterceptor extends TransactionAspectSupport imp
|
||||
final TransactionAttribute txnAttr = getTransactionAttributeSource().getTransactionAttribute(
|
||||
method, invocation.getThis().getClass());
|
||||
|
||||
final TransactionManager tm = determineTransactionManager(txnAttr);
|
||||
final TransactionManager tm = determineTransactionManager(txnAttr, null);
|
||||
|
||||
if (tm != null && !(tm instanceof PlatformTransactionManager))
|
||||
{
|
||||
@@ -83,8 +84,7 @@ public class RetryingTransactionInterceptor extends TransactionAspectSupport imp
|
||||
retryingTransactionHelper.setExtraExceptions(extraExceptions);
|
||||
|
||||
return retryingTransactionHelper.doInTransaction(
|
||||
new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
new RetryingTransactionCallback<Object>() {
|
||||
public Object execute()
|
||||
{
|
||||
TransactionInfo txInfo = createTransactionIfNecessary(ptm, TransactionAttribute.PROPAGATION_REQUIRES_NEW == txnAttr
|
||||
|
@@ -1394,6 +1394,9 @@ scripts.execution.maxMemoryUsedInBytes=-1
|
||||
# Number of instructions that will trigger the observer
|
||||
scripts.execution.observerInstructionCount=5000
|
||||
|
||||
# Flag to control if the scope is cleaned at the end of script execution
|
||||
scripts.execution.clean.scope=true
|
||||
|
||||
# Default value being used in POST/size-details endpoint to partition a huge folder into smaller chunks
|
||||
# so that we can compute more efficiently and consolidate all sizes into a single unit.
|
||||
default.async.folder.items=1000
|
||||
|
@@ -60,6 +60,9 @@
|
||||
<property name="observerInstructionCount">
|
||||
<value>${scripts.execution.observerInstructionCount}</value>
|
||||
</property>
|
||||
<property name="cleanScope">
|
||||
<value>${scripts.execution.clean.scope}</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- base config implementation that script extension beans extend from - for auto registration
|
||||
|
@@ -26,6 +26,12 @@
|
||||
|
||||
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 java.io.Serializable;
|
||||
@@ -35,6 +41,9 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
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.util.GUID;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Iulian Aftene
|
||||
@@ -66,20 +74,20 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
public void testUpdateNodeResourceContent()
|
||||
{
|
||||
ContentService contentService = (ContentService) applicationContext.getBean(
|
||||
"contentService");
|
||||
"contentService");
|
||||
|
||||
final NodeRef nodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
|
||||
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEvent(1);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(),
|
||||
resultRepoEvent.getType());
|
||||
resultRepoEvent.getType());
|
||||
|
||||
NodeResource resource = getNodeResource(resultRepoEvent);
|
||||
assertNull("Content should have been null.", resource.getContent());
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.TYPE_CONTENT,
|
||||
true);
|
||||
true);
|
||||
writer.setMimetype(MimetypeMap.MIMETYPE_PDF);
|
||||
writer.setEncoding("UTF-8");
|
||||
writer.putContent("test content.");
|
||||
@@ -90,7 +98,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
|
||||
resultRepoEvent = getRepoEvent(2);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(),
|
||||
resultRepoEvent.getType());
|
||||
resultRepoEvent.getType());
|
||||
|
||||
resource = getNodeResource(resultRepoEvent);
|
||||
ContentInfo content = resource.getContent();
|
||||
@@ -105,7 +113,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
// Update the content again
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.TYPE_CONTENT,
|
||||
true);
|
||||
true);
|
||||
writer.setMimetype(MimetypeMap.MIMETYPE_PDF);
|
||||
writer.setEncoding("UTF-8");
|
||||
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", getLocalizedProperty(resource, "cm:title", defaultLocale));
|
||||
|
||||
|
||||
resourceBefore = getNodeResourceBefore(3);
|
||||
title = getProperty(resourceBefore, "cm:title");
|
||||
assertEquals("Wrong old property.", "test title", title);
|
||||
@@ -490,14 +497,14 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
resource = getNodeResource(2);
|
||||
assertNotNull(resource.getAspectNames());
|
||||
assertTrue(resource.getAspectNames().contains("cm:versionable"));
|
||||
//Check all aspects
|
||||
// Check all aspects
|
||||
Set<String> expectedAspects = new HashSet<>(originalAspects);
|
||||
expectedAspects.add("cm:versionable");
|
||||
assertEquals(expectedAspects, resource.getAspectNames());
|
||||
// Check properties
|
||||
assertFalse(resource.getProperties().isEmpty());
|
||||
|
||||
//Check resourceBefore
|
||||
// Check resourceBefore
|
||||
NodeResource resourceBefore = getNodeResourceBefore(2);
|
||||
assertNotNull(resourceBefore.getAspectNames());
|
||||
assertEquals(originalAspects, resourceBefore.getAspectNames());
|
||||
@@ -544,21 +551,64 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
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
|
||||
public void testCreateAndUpdateInTheSameTransaction()
|
||||
{
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
|
||||
NodeRef node1 = nodeService.createNode(
|
||||
rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName(TEST_NAMESPACE, GUID.generate()),
|
||||
ContentModel.TYPE_CONTENT).getChildRef();
|
||||
rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName(TEST_NAMESPACE, GUID.generate()),
|
||||
ContentModel.TYPE_CONTENT).getChildRef();
|
||||
|
||||
nodeService.setProperty(node1, PROP_DESCRIPTION, "test description");
|
||||
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
|
||||
checkNumOfEvents(1);
|
||||
}
|
||||
@@ -593,8 +643,8 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
assertEquals("Incorrect node type was found", "cm:folder", nodeResource.getNodeType());
|
||||
|
||||
NodeResource resourceBefore = getNodeResourceBefore(2);
|
||||
assertEquals("Incorrect node type was found","cm:content", resourceBefore.getNodeType());
|
||||
// assertNotNull(resourceBefore.getModifiedAt()); uncomment this when the issue will be fixed
|
||||
assertEquals("Incorrect node type was found", "cm:content", resourceBefore.getNodeType());
|
||||
// assertNotNull(resourceBefore.getModifiedAt()); uncomment this when the issue will be fixed
|
||||
assertNull(resourceBefore.getId());
|
||||
assertNull(resourceBefore.getContent());
|
||||
assertNull(resourceBefore.isFile());
|
||||
@@ -624,8 +674,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
m2Type.setTitle("Test type title");
|
||||
|
||||
// Create active model
|
||||
CustomModelDefinition modelDefinition =
|
||||
retryingTransactionHelper.doInTransaction(() -> customModelService.createCustomModel(model, true));
|
||||
CustomModelDefinition modelDefinition = retryingTransactionHelper.doInTransaction(() -> customModelService.createCustomModel(model, true));
|
||||
|
||||
assertNotNull(modelDefinition);
|
||||
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("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(() -> {
|
||||
nodeService.setType(nodeRef, typeQName);
|
||||
|
||||
@@ -757,7 +806,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
// we should have only 1 event, node.Created
|
||||
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());
|
||||
NodeResource nodeResource = getNodeResource(resultRepoEvent);
|
||||
assertEquals("Incorrect node type was found", "cm:folder", nodeResource.getNodeType());
|
||||
@@ -783,10 +832,10 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
nodeService.moveNode(
|
||||
moveFile,
|
||||
folder2,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE));
|
||||
moveFile,
|
||||
folder2,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE));
|
||||
return null;
|
||||
});
|
||||
|
||||
@@ -801,7 +850,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
assertEquals("Wrong node parent.", folder1ID, moveFileParentBeforeMove);
|
||||
assertEquals("Wrong node parent.", folder2ID, moveFileParentAfterMove);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(),
|
||||
getRepoEvent(4).getType());
|
||||
getRepoEvent(4).getType());
|
||||
|
||||
assertNull(resourceBefore.getId());
|
||||
assertNull(resourceBefore.getName());
|
||||
@@ -833,10 +882,10 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
nodeService.moveNode(
|
||||
moveFolder,
|
||||
grandParent,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE));
|
||||
moveFolder,
|
||||
grandParent,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE));
|
||||
return null;
|
||||
});
|
||||
|
||||
@@ -845,15 +894,13 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
final String grandParentID = getNodeResource(1).getId();
|
||||
final String parentID = getNodeResource(2).getId();
|
||||
|
||||
final String moveFolderParentBeforeMove =
|
||||
getNodeResourceBefore(4).getPrimaryHierarchy().get(0);
|
||||
final String moveFolderParentAfterMove =
|
||||
getNodeResource(4).getPrimaryHierarchy().get(0);
|
||||
final String moveFolderParentBeforeMove = getNodeResourceBefore(4).getPrimaryHierarchy().get(0);
|
||||
final String moveFolderParentAfterMove = getNodeResource(4).getPrimaryHierarchy().get(0);
|
||||
|
||||
assertEquals("Wrong node parent.", parentID, moveFolderParentBeforeMove);
|
||||
assertEquals("Wrong node parent.", grandParentID, moveFolderParentAfterMove);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(),
|
||||
getRepoEventWithoutWait(4).getType());
|
||||
getRepoEventWithoutWait(4).getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -867,28 +914,25 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
nodeService.moveNode(
|
||||
grandParent,
|
||||
root2,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE));
|
||||
grandParent,
|
||||
root2,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE));
|
||||
return null;
|
||||
});
|
||||
|
||||
checkNumOfEvents(6);
|
||||
|
||||
final String root2ID = getNodeResource(2).getId();
|
||||
final String grandParentParentAfterMove =
|
||||
getNodeResource(6).getPrimaryHierarchy().get(0);
|
||||
final String grandParentParentAfterMove = getNodeResource(6).getPrimaryHierarchy().get(0);
|
||||
assertEquals("Wrong node parent.", root2ID, grandParentParentAfterMove);
|
||||
|
||||
final String grandParentID = getNodeResource(3).getId();
|
||||
final String parentIDOfTheParentFolder =
|
||||
getNodeResource(4).getPrimaryHierarchy().get(0);
|
||||
final String parentIDOfTheParentFolder = getNodeResource(4).getPrimaryHierarchy().get(0);
|
||||
assertEquals("Wrong node parent.", grandParentID, parentIDOfTheParentFolder);
|
||||
|
||||
final String parentID = getNodeResource(4).getId();
|
||||
final String contentParentID =
|
||||
getNodeResource(5).getPrimaryHierarchy().get(0);
|
||||
final String contentParentID = getNodeResource(5).getPrimaryHierarchy().get(0);
|
||||
assertEquals("Wrong node parent.", parentID, contentParentID);
|
||||
}
|
||||
|
||||
@@ -906,10 +950,10 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
nodeService.moveNode(
|
||||
moveFile,
|
||||
folder2,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE));
|
||||
moveFile,
|
||||
folder2,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE));
|
||||
return null;
|
||||
});
|
||||
|
||||
@@ -918,8 +962,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
assertTrue("Wrong aspect.", resource.getAspectNames().contains("cm:versionable"));
|
||||
|
||||
final String folder2ID = getNodeResource(2).getId();
|
||||
final String moveFileParentAfterMove =
|
||||
getNodeResource(5).getPrimaryHierarchy().get(0);
|
||||
final String moveFileParentAfterMove = getNodeResource(5).getPrimaryHierarchy().get(0);
|
||||
|
||||
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.moveNode(
|
||||
moveFile,
|
||||
folder2,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE));
|
||||
moveFile,
|
||||
folder2,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE));
|
||||
return null;
|
||||
});
|
||||
|
||||
@@ -946,8 +989,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
assertEquals("test_new_name", resource.getName());
|
||||
|
||||
final String folder2ID = getNodeResource(2).getId();
|
||||
final String moveFileParentAfterMove =
|
||||
getNodeResource(4).getPrimaryHierarchy().get(0);
|
||||
final String moveFileParentAfterMove = getNodeResource(4).getPrimaryHierarchy().get(0);
|
||||
|
||||
assertEquals("Wrong node parent.", folder2ID, moveFileParentAfterMove);
|
||||
}
|
||||
@@ -958,28 +1000,28 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
|
||||
NodeRef folder1 = nodeService.createNode(
|
||||
rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName(TEST_NAMESPACE),
|
||||
ContentModel.TYPE_FOLDER).getChildRef();
|
||||
rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName(TEST_NAMESPACE),
|
||||
ContentModel.TYPE_FOLDER).getChildRef();
|
||||
|
||||
NodeRef folder2 = nodeService.createNode(
|
||||
rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName(TEST_NAMESPACE),
|
||||
ContentModel.TYPE_FOLDER).getChildRef();
|
||||
rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName(TEST_NAMESPACE),
|
||||
ContentModel.TYPE_FOLDER).getChildRef();
|
||||
|
||||
NodeRef fileToMove = nodeService.createNode(
|
||||
folder1,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE),
|
||||
ContentModel.TYPE_CONTENT).getChildRef();
|
||||
folder1,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE),
|
||||
ContentModel.TYPE_CONTENT).getChildRef();
|
||||
|
||||
nodeService.moveNode(
|
||||
fileToMove,
|
||||
folder2,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE));
|
||||
fileToMove,
|
||||
folder2,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE));
|
||||
|
||||
assertEquals(folder2, nodeService.getPrimaryParent(fileToMove).getParentRef());
|
||||
|
||||
@@ -989,8 +1031,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
checkNumOfEvents(3);
|
||||
|
||||
final String folder2ID = getNodeResource(2).getId();
|
||||
final String moveFileParentAfterMove =
|
||||
getNodeResource(3).getPrimaryHierarchy().get(0);
|
||||
final String moveFileParentAfterMove = getNodeResource(3).getPrimaryHierarchy().get(0);
|
||||
|
||||
assertEquals("Wrong node parent.", folder2ID, moveFileParentAfterMove);
|
||||
}
|
||||
@@ -1003,7 +1044,6 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
final Set<String> originalAspects = resource.getAspectNames();
|
||||
assertNotNull(originalAspects);
|
||||
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
// Add cm:geographic aspect with default value
|
||||
nodeService.addAspect(nodeRef, ContentModel.ASPECT_GEOGRAPHIC, null);
|
||||
|
@@ -39,6 +39,7 @@ import org.junit.Test;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.model.RenditionModel;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
@@ -776,4 +777,57 @@ public class RenditionService2IntegrationTest extends AbstractRenditionIntegrati
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,55 +1,54 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.util;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* Base test class providing Hibernate sessions.
|
||||
* <p>
|
||||
* By default this is auto-wired by type. If a this is going to
|
||||
* result in a conlict the use auto-wire by name. This can be done by
|
||||
* setting populateProtectedVariables to true in the constructor and
|
||||
* then adding protected members with the same name as the bean you require.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration({"classpath:alfresco/application-context.xml"})
|
||||
public abstract class BaseSpringTest extends TestCase
|
||||
{
|
||||
public Log logger = LogFactory.getLog(getClass().getName());
|
||||
|
||||
@Autowired
|
||||
protected ApplicationContext applicationContext;
|
||||
}
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.util;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.ContextCustomizerFactories;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* Base test class providing Hibernate sessions.
|
||||
* <p>
|
||||
* By default this is auto-wired by type. If a this is going to result in a conlict the use auto-wire by name. This can be done by setting populateProtectedVariables to true in the constructor and then adding protected members with the same name as the bean you require.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration({"classpath:alfresco/application-context.xml"})
|
||||
@ContextCustomizerFactories(factories = {}, mergeMode = ContextCustomizerFactories.MergeMode.REPLACE_DEFAULTS)
|
||||
public abstract class BaseSpringTest extends TestCase
|
||||
{
|
||||
public Log logger = LogFactory.getLog(getClass().getName());
|
||||
|
||||
@Autowired
|
||||
protected ApplicationContext applicationContext;
|
||||
}
|
||||
|
Reference in New Issue
Block a user