From 3b6b7a747631a191dd0ca4751209fda20b7f914f Mon Sep 17 00:00:00 2001 From: milanmajchrak Date: Mon, 29 Jun 2026 16:39:23 +0200 Subject: [PATCH] fix: guard null owning collection in CanManageMappingsFeature CanManageMappingsFeature.isAuthorized dereferenced item.getOwningCollection().getID() with no null check, so evaluating the canManageMappings feature for an item whose owning_collection is NULL threw a NullPointerException (HTTP 500). This surfaced on the item edit page via GET /api/authz/authorizations/search/object for users with WRITE (admins). Resolve the owning collection once and treat null as "no collection to exclude" in the filter, mirroring the defensive pattern already used by DeleteFeature. Also guard against itemService.find returning null. Co-Authored-By: Claude Opus 4.8 --- .../rest/authorization/impl/CanManageMappingsFeature.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/authorization/impl/CanManageMappingsFeature.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/authorization/impl/CanManageMappingsFeature.java index 75e83860dd4a..37356c8006bf 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/authorization/impl/CanManageMappingsFeature.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/authorization/impl/CanManageMappingsFeature.java @@ -64,14 +64,18 @@ public boolean isAuthorized(Context context, BaseObjectRest object) throws SQLEx } if (object instanceof ItemRest) { Item item = itemService.find(context, UUID.fromString(((ItemRest) object).getUuid())); - if (!authorizeService.authorizeActionBoolean(context, item, Constants.WRITE)) { + if (item == null || !authorizeService.authorizeActionBoolean(context, item, Constants.WRITE)) { return false; } + // An orphaned item (e.g. one whose owning collection was lost) has no owning collection. + // Guard against it so the feature evaluation does not throw a NullPointerException. + Collection owningCollection = item.getOwningCollection(); try { Optional collections = collectionService.findCollectionsWithSubmit(StringUtils.EMPTY, context, null, 0, Integer.MAX_VALUE) .stream() - .filter(c -> !c.getID().equals(item.getOwningCollection().getID())) + .filter(c -> owningCollection == null + || !c.getID().equals(owningCollection.getID())) .filter(c -> { try { return collectionService.canEditBoolean(context, c);