[TLC-1117] Inherit custom, non-admin policies when creating new bundles

Also shifted some resource policy methods from ItemService to
AuthorizeService as they seemed better suited there.
This commit is contained in:
Kim Shepherd
2025-05-26 10:15:40 +02:00
parent cac7eec084
commit 924678a092
4 changed files with 235 additions and 94 deletions

View File

@@ -480,7 +480,7 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl<Item> implements It
// now add authorization policies from owning item
// hmm, not very "multiple-inclusion" friendly
authorizeService.inheritPolicies(context, item, bundle);
authorizeService.inheritPolicies(context, item, bundle, true);
// Add the bundle to in-memory list
item.addBundle(bundle);
@@ -1046,8 +1046,8 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl<Item> implements It
// if come from InstallItem: remove all submission/workflow policies
authorizeService.removeAllPoliciesByDSOAndType(context, mybundle, ResourcePolicy.TYPE_SUBMISSION);
authorizeService.removeAllPoliciesByDSOAndType(context, mybundle, ResourcePolicy.TYPE_WORKFLOW);
addCustomPoliciesNotInPlace(context, mybundle, defaultItemPolicies);
addDefaultPoliciesNotInPlace(context, mybundle, defaultCollectionBundlePolicies);
authorizeService.addCustomPoliciesNotInPlace(context, mybundle, defaultItemPolicies);
authorizeService.addDefaultPoliciesNotInPlace(context, mybundle, defaultCollectionBundlePolicies);
for (Bitstream bitstream : mybundle.getBitstreams()) {
// If collection has default READ policies, remove the bundle's READ policies.
@@ -1093,8 +1093,8 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl<Item> implements It
throws SQLException, AuthorizeException {
authorizeService.removeAllPoliciesByDSOAndType(context, bitstream, ResourcePolicy.TYPE_SUBMISSION);
authorizeService.removeAllPoliciesByDSOAndType(context, bitstream, ResourcePolicy.TYPE_WORKFLOW);
addCustomPoliciesNotInPlace(context, bitstream, defaultItemPolicies);
addDefaultPoliciesNotInPlace(context, bitstream, defaultCollectionPolicies);
authorizeService.addCustomPoliciesNotInPlace(context, bitstream, defaultItemPolicies);
authorizeService.addDefaultPoliciesNotInPlace(context, bitstream, defaultCollectionPolicies);
}
@Override
@@ -1132,7 +1132,7 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl<Item> implements It
authorizeService.removeAllPoliciesByDSOAndType(context, item, ResourcePolicy.TYPE_WORKFLOW);
// add default policies only if not already in place
addDefaultPoliciesNotInPlace(context, item, defaultCollectionPolicies);
authorizeService.addDefaultPoliciesNotInPlace(context, item, defaultCollectionPolicies);
} finally {
context.restoreAuthSystemState();
}
@@ -1322,91 +1322,7 @@ prevent the generation of resource policy entry values with null dspace_object a
*/
/**
* Add the default policies, which have not been already added to the given DSpace object
*
* @param context The relevant DSpace Context.
* @param dso The DSpace Object to add policies to
* @param defaultCollectionPolicies list of policies
* @throws SQLException An exception that provides information on a database access error or other errors.
* @throws AuthorizeException Exception indicating the current user of the context does not have permission
* to perform a particular action.
*/
protected void addDefaultPoliciesNotInPlace(Context context, DSpaceObject dso,
List<ResourcePolicy> defaultCollectionPolicies) throws SQLException, AuthorizeException {
boolean appendMode = configurationService
.getBooleanProperty("core.authorization.installitem.inheritance-read.append-mode", false);
for (ResourcePolicy defaultPolicy : defaultCollectionPolicies) {
if (!authorizeService
.isAnIdenticalPolicyAlreadyInPlace(context, dso, defaultPolicy.getGroup(), Constants.READ,
defaultPolicy.getID()) &&
(!appendMode && isNotAlreadyACustomRPOfThisTypeOnDSO(context, dso) ||
appendMode && shouldBeAppended(context, dso, defaultPolicy))) {
ResourcePolicy newPolicy = resourcePolicyService.clone(context, defaultPolicy);
newPolicy.setdSpaceObject(dso);
newPolicy.setAction(Constants.READ);
newPolicy.setRpType(ResourcePolicy.TYPE_INHERITED);
resourcePolicyService.update(context, newPolicy);
}
}
}
private void addCustomPoliciesNotInPlace(Context context, DSpaceObject dso, List<ResourcePolicy> customPolicies)
throws SQLException, AuthorizeException {
boolean customPoliciesAlreadyInPlace = authorizeService
.findPoliciesByDSOAndType(context, dso, ResourcePolicy.TYPE_CUSTOM).size() > 0;
if (!customPoliciesAlreadyInPlace) {
authorizeService.addPolicies(context, customPolicies, dso);
}
}
/**
* Check whether or not there is already an RP on the given dso, which has actionId={@link Constants.READ} and
* resourceTypeId={@link ResourcePolicy.TYPE_CUSTOM}
*
* @param context DSpace context
* @param dso DSpace object to check for custom read RP
* @return True if there is no RP on the item with custom read RP, otherwise false
* @throws SQLException If something goes wrong retrieving the RP on the DSO
*/
private boolean isNotAlreadyACustomRPOfThisTypeOnDSO(Context context, DSpaceObject dso) throws SQLException {
List<ResourcePolicy> readRPs = resourcePolicyService.find(context, dso, Constants.READ);
for (ResourcePolicy readRP : readRPs) {
if (readRP.getRpType() != null && readRP.getRpType().equals(ResourcePolicy.TYPE_CUSTOM)) {
return false;
}
}
return true;
}
/**
* Check if the provided default policy should be appended or not to the final
* item. If an item has at least one custom READ policy any anonymous READ
* policy with empty start/end date should be skipped
*
* @param context DSpace context
* @param dso DSpace object to check for custom read RP
* @param defaultPolicy The policy to check
* @return
* @throws SQLException If something goes wrong retrieving the RP on the DSO
*/
private boolean shouldBeAppended(Context context, DSpaceObject dso, ResourcePolicy defaultPolicy)
throws SQLException {
boolean hasCustomPolicy = resourcePolicyService.find(context, dso, Constants.READ)
.stream()
.filter(rp -> (Objects.nonNull(rp.getRpType()) &&
Objects.equals(rp.getRpType(), ResourcePolicy.TYPE_CUSTOM)))
.findFirst()
.isPresent();
boolean isAnonimousGroup = Objects.nonNull(defaultPolicy.getGroup())
&& StringUtils.equals(defaultPolicy.getGroup().getName(), Group.ANONYMOUS);
boolean datesAreNull = Objects.isNull(defaultPolicy.getStartDate())
&& Objects.isNull(defaultPolicy.getEndDate());
return !(hasCustomPolicy && isAnonimousGroup && datesAreNull);
}
/**
* Returns an iterator of Items possessing the passed metadata field, or only