Skip to content

Commit d35e377

Browse files
authored
UFAL/Added provenance when resource policy changed (#1105)
* added provenacne when resource policy changed * separated method, removed bitstream check * removed unneeded method, use isNull from Objects * removed unwanted tests created by copilot
1 parent c662a79 commit d35e377

8 files changed

Lines changed: 179 additions & 1 deletion

File tree

dspace-api/src/main/java/org/dspace/core/ProvenanceMessageFormatter.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ public String getMessage(Context context, String messageTemplate, Object... args
5050
EPerson currentUser = context.getCurrentUser();
5151
String timestamp = DCDate.getCurrent().toString();
5252
String details = validateMessageTemplate(messageTemplate, args);
53+
54+
// Handle null user case
55+
if (currentUser == null) {
56+
return String.format("%s by None on %s",
57+
details,
58+
timestamp);
59+
}
60+
5361
return String.format("%s by %s (%s) on %s",
5462
details,
5563
currentUser.getFullName(),
@@ -87,6 +95,29 @@ public String getMessage(List<ResourcePolicy> resPolicies) {
8795
.collect(Collectors.joining(";"));
8896
}
8997

98+
public String getMessage(ResourcePolicy resourcePolicy) {
99+
StringBuilder sb = new StringBuilder();
100+
sb.append("[Action: ")
101+
.append(Constants.actionText[resourcePolicy.getAction()]);
102+
if (resourcePolicy.getEPerson() != null) {
103+
sb.append(", EPerson: ").append(resourcePolicy.getEPerson().getEmail());
104+
}
105+
if (resourcePolicy.getGroup() != null) {
106+
sb.append(", Group: ").append(resourcePolicy.getGroup().getName());
107+
}
108+
if (resourcePolicy.getStartDate() != null) {
109+
sb.append(", Start: ").append(resourcePolicy.getStartDate().toString());
110+
}
111+
if (resourcePolicy.getEndDate() != null) {
112+
sb.append(", End: ").append(resourcePolicy.getEndDate().toString());
113+
}
114+
if (resourcePolicy.getRpDescription() != null) {
115+
sb.append(", Description: ").append(resourcePolicy.getRpDescription());
116+
}
117+
sb.append("]");
118+
return sb.toString();
119+
}
120+
90121
public String getMetadata(String oldMtdKey, String oldMtdValue) {
91122
return oldMtdKey + ": " + oldMtdValue;
92123
}

dspace-api/src/main/java/org/dspace/core/ProvenanceMessageTemplates.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ public enum ProvenanceMessageTemplates {
2424
ITEM_METADATA("Item metadata (%s) was %s"),
2525
BITSTREAM_METADATA("Item metadata (%s) was %s bitstream (%s)"),
2626
ITEM_REPLACE_SINGLE_METADATA("Item bitstream (%s) metadata (%s) was updated"),
27-
DISCOVERABLE("Item was made %sdiscoverable");
27+
DISCOVERABLE("Item was made %sdiscoverable"),
28+
RESOURCE_POLICY_CREATED("Resource policy created: %s for %s (%s)"),
29+
RESOURCE_POLICY_UPDATED("Resource policy updated: %s for %s (%s)"),
30+
RESOURCE_POLICY_DELETED("Resource policy deleted: %s for %s (%s)");
2831

2932
private final String template;
3033

dspace-api/src/main/java/org/dspace/core/ProvenanceService.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,30 @@ void replaceMetadataSingle(Context context, DSpaceObject dso, MetadataField meta
179179
*/
180180
void uploadBitstream(Context context, Bundle bundle);
181181

182+
/**
183+
* Add a provenance message to the item when a resource policy is created
184+
*
185+
* @param context DSpace context object
186+
* @param resourcePolicy the resource policy that was created
187+
*/
188+
void createResourcePolicy(Context context, ResourcePolicy resourcePolicy);
189+
190+
/**
191+
* Add a provenance message to the item when a resource policy is updated
192+
*
193+
* @param context DSpace context object
194+
* @param resourcePolicy the resource policy that was updated
195+
*/
196+
void updateResourcePolicy(Context context, ResourcePolicy resourcePolicy);
197+
198+
/**
199+
* Add a provenance message to the item when a resource policy is deleted
200+
*
201+
* @param context DSpace context object
202+
* @param resourcePolicy the resource policy that was deleted
203+
*/
204+
void deleteResourcePolicy(Context context, ResourcePolicy resourcePolicy);
205+
182206
/**
183207
* Fetch an Item object using a service and return the first Item object from the list.
184208
* Log an error if the list is empty or if there is an SQL error

dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,101 @@ public Item findItemByBitstream(Context context, Bitstream bitstream) {
350350
return items.get(0);
351351
}
352352

353+
@Override
354+
public void createResourcePolicy(Context context, ResourcePolicy resourcePolicy) {
355+
if (Objects.isNull(resourcePolicy.getdSpaceObject())) {
356+
return;
357+
}
358+
359+
DSpaceObject dso = resourcePolicy.getdSpaceObject();
360+
String resourcePolicyStr = messageProvider.getMessage(resourcePolicy);
361+
String dsoType = getDSpaceObjectType(dso.getType());
362+
363+
try {
364+
if (dso.getType() != Constants.ITEM) {
365+
log.warn("Provenance message for resource policy creation is supported only for items." +
366+
" DSpace object type: " + dsoType);
367+
return;
368+
}
369+
Item item = (Item) dso;
370+
String msg = messageProvider.getMessage(context,
371+
ProvenanceMessageTemplates.RESOURCE_POLICY_CREATED.getTemplate(),
372+
resourcePolicyStr, dsoType, item.getID());
373+
addProvenanceMetadata(context, item, msg);
374+
} catch (SQLException | AuthorizeException e) {
375+
log.error("Unable to add new provenance metadata when creating resource policy.", e);
376+
}
377+
}
378+
379+
@Override
380+
public void updateResourcePolicy(Context context, ResourcePolicy resourcePolicy) {
381+
if (Objects.isNull(resourcePolicy.getdSpaceObject())) {
382+
return;
383+
}
384+
385+
DSpaceObject dso = resourcePolicy.getdSpaceObject();
386+
String resourcePolicyStr = messageProvider.getMessage(resourcePolicy);
387+
String dsoType = getDSpaceObjectType(dso.getType());
388+
389+
try {
390+
if (dso.getType() != Constants.ITEM) {
391+
log.warn("Provenance message for resource policy update is supported only for items. " +
392+
"Current DSpace object type: " + dsoType);
393+
return;
394+
}
395+
Item item = (Item) dso;
396+
String msg = messageProvider.getMessage(context,
397+
ProvenanceMessageTemplates.RESOURCE_POLICY_UPDATED.getTemplate(),
398+
resourcePolicyStr, dsoType, item.getID());
399+
addProvenanceMetadata(context, item, msg);
400+
} catch (SQLException | AuthorizeException e) {
401+
log.error("Unable to add new provenance metadata when updating resource policy.", e);
402+
}
403+
}
404+
405+
@Override
406+
public void deleteResourcePolicy(Context context, ResourcePolicy resourcePolicy) {
407+
if (Objects.isNull(resourcePolicy.getdSpaceObject())) {
408+
return;
409+
}
410+
411+
DSpaceObject dso = resourcePolicy.getdSpaceObject();
412+
String resourcePolicyStr = messageProvider.getMessage(resourcePolicy);
413+
String dsoType = getDSpaceObjectType(dso.getType());
414+
415+
try {
416+
if (dso.getType() != Constants.ITEM) {
417+
log.warn("Provenance message for resource policy deletion is supported only for items. " +
418+
"The current DSpace object type is: " + dsoType);
419+
return;
420+
}
421+
Item item = (Item) dso;
422+
String msg = messageProvider.getMessage(context,
423+
ProvenanceMessageTemplates.RESOURCE_POLICY_DELETED.getTemplate(),
424+
resourcePolicyStr, dsoType, item.getID());
425+
addProvenanceMetadata(context, item, msg);
426+
} catch (SQLException | AuthorizeException e) {
427+
log.error("Unable to add new provenance metadata when deleting resource policy.", e);
428+
}
429+
}
430+
431+
private String getDSpaceObjectType(int type) {
432+
switch (type) {
433+
case Constants.ITEM:
434+
return "item";
435+
case Constants.BITSTREAM:
436+
return "bitstream";
437+
case Constants.COLLECTION:
438+
return "collection";
439+
case Constants.COMMUNITY:
440+
return "community";
441+
case Constants.BUNDLE:
442+
return "bundle";
443+
default:
444+
return "object";
445+
}
446+
}
447+
353448
private String findLicenseInBundles(Item item, String bundleName, String currentLicense, Context context)
354449
throws SQLException {
355450
List<Bundle> bundles = item.getBundles(bundleName);

dspace-server-webapp/src/main/java/org/dspace/app/rest/ResourcePolicyEPersonReplaceRestController.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.dspace.authorize.service.ResourcePolicyService;
2626
import org.dspace.content.DSpaceObject;
2727
import org.dspace.core.Context;
28+
import org.dspace.core.ProvenanceService;
2829
import org.dspace.eperson.EPerson;
2930
import org.springframework.beans.factory.annotation.Autowired;
3031
import org.springframework.data.rest.webmvc.ControllerUtils;
@@ -51,6 +52,8 @@ public class ResourcePolicyEPersonReplaceRestController {
5152
private Utils utils;
5253
@Autowired
5354
private ResourcePolicyService resourcePolicyService;
55+
@Autowired
56+
private ProvenanceService provenanceService;
5457

5558
@PreAuthorize("hasPermission(#id, 'resourcepolicy', 'ADMIN')")
5659
@RequestMapping(method = PUT, consumes = {"text/uri-list"})
@@ -75,6 +78,7 @@ public ResponseEntity<RepresentationModel<?>> replaceEPersonOfResourcePolicy(@Pa
7578
}
7679
EPerson newEPerson = (EPerson) dsoList.get(0);
7780
resourcePolicy.setEPerson(newEPerson);
81+
provenanceService.updateResourcePolicy(context, resourcePolicy);
7882
context.commit();
7983
return ControllerUtils.toEmptyResponse(HttpStatus.NO_CONTENT);
8084
}

dspace-server-webapp/src/main/java/org/dspace/app/rest/ResourcePolicyGroupReplaceRestController.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.dspace.authorize.service.ResourcePolicyService;
2626
import org.dspace.content.DSpaceObject;
2727
import org.dspace.core.Context;
28+
import org.dspace.core.ProvenanceService;
2829
import org.dspace.eperson.Group;
2930
import org.springframework.beans.factory.annotation.Autowired;
3031
import org.springframework.data.rest.webmvc.ControllerUtils;
@@ -51,6 +52,8 @@ public class ResourcePolicyGroupReplaceRestController {
5152
private Utils utils;
5253
@Autowired
5354
private ResourcePolicyService resourcePolicyService;
55+
@Autowired
56+
private ProvenanceService provenanceService;
5457

5558
@PreAuthorize("hasPermission(#id, 'resourcepolicy', 'ADMIN')")
5659
@RequestMapping(method = PUT, consumes = {"text/uri-list"})
@@ -75,6 +78,7 @@ public ResponseEntity<RepresentationModel<?>> replaceGroupOfResourcePolicy(@Path
7578

7679
Group newGroup = (Group) dsoList.get(0);
7780
resourcePolicy.setGroup(newGroup);
81+
provenanceService.updateResourcePolicy(context, resourcePolicy);
7882
context.commit();
7983
return ControllerUtils.toEmptyResponse(HttpStatus.NO_CONTENT);
8084
}

dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ResourcePolicyRestRepository.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.dspace.content.Item;
3838
import org.dspace.core.Constants;
3939
import org.dspace.core.Context;
40+
import org.dspace.core.ProvenanceService;
4041
import org.dspace.eperson.EPerson;
4142
import org.dspace.eperson.Group;
4243
import org.dspace.eperson.service.EPersonService;
@@ -88,6 +89,9 @@ public class ResourcePolicyRestRepository extends DSpaceRestRepository<ResourceP
8889
@Autowired
8990
private SolrOAIReindexer solrOAIReindexer;
9091

92+
@Autowired
93+
private ProvenanceService provenanceService;
94+
9195
@Override
9296
@PreAuthorize("hasPermission(#id, 'resourcepolicy', 'READ')")
9397
public ResourcePolicyRest findOne(Context context, Integer id) {
@@ -339,6 +343,7 @@ protected ResourcePolicyRest createAndReturn(Context context) throws AuthorizeEx
339343
resourcePolicy.setStartDate(resourcePolicyRest.getStartDate());
340344
resourcePolicy.setEndDate(resourcePolicyRest.getEndDate());
341345
resourcePolicyService.update(context, resourcePolicy);
346+
provenanceService.createResourcePolicy(context, resourcePolicy);
342347
return converter.toRest(resourcePolicy, utils.obtainProjection());
343348
} else {
344349
throw new UnprocessableEntityException("A resource policy must contain a valid eperson or group");
@@ -358,6 +363,7 @@ protected void delete(Context context, Integer id) throws AuthorizeException {
358363
ResourcePolicyRest.CATEGORY + "." + ResourcePolicyRest.NAME + " with id: " + id + " not found");
359364
}
360365
dso = resourcePolicy.getdSpaceObject();
366+
provenanceService.deleteResourcePolicy(context, resourcePolicy);
361367
resourcePolicyService.delete(context, resourcePolicy);
362368
} catch (SQLException e) {
363369
throw new RuntimeException("Unable to delete ResourcePolicy with id = " + id, e);
@@ -378,6 +384,7 @@ protected void patch(Context context, HttpServletRequest request, String apiCate
378384
}
379385
resourcePatch.patch(obtainContext(), resourcePolicy, patch.getOperations());
380386
resourcePolicyService.update(context, resourcePolicy);
387+
provenanceService.updateResourcePolicy(context, resourcePolicy);
381388
reindexSolrOAI(resourcePolicy.getdSpaceObject());
382389
}
383390

dspace-server-webapp/src/test/java/org/dspace/app/rest/ResourcePolicyRestRepositoryIT.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
import org.dspace.eperson.EPerson;
6363
import org.dspace.eperson.Group;
6464
import org.dspace.eperson.factory.EPersonServiceFactory;
65+
import org.dspace.eperson.service.EPersonService;
6566
import org.hamcrest.Matchers;
6667
import org.junit.Ignore;
6768
import org.junit.Test;
@@ -77,6 +78,9 @@ public class ResourcePolicyRestRepositoryIT extends AbstractControllerIntegratio
7778
@Autowired
7879
AuthorizeService authorizeService;
7980

81+
@Autowired
82+
EPersonService ePersonService;
83+
8084
@Autowired
8185
ResourcePolicyService resourcePolicyService;
8286

@@ -1736,6 +1740,12 @@ public void deletePolicyByCollectionAdminTest() throws Exception {
17361740

17371741
context.restoreAuthSystemState();
17381742

1743+
colAdmin = ePersonService.find(context, colAdmin.getID());
1744+
colAdmin2 = ePersonService.find(context, colAdmin2.getID());
1745+
submitter = ePersonService.find(context, submitter.getID());
1746+
1747+
context.setCurrentUser(submitter);
1748+
17391749
String adminToken = getAuthToken(admin.getEmail(), password);
17401750
String authcolAdminToken = getAuthToken(colAdmin.getEmail(), password);
17411751
String authcolAdmin2Token = getAuthToken(colAdmin2.getEmail(), password);

0 commit comments

Comments
 (0)