From 8a1a7738bcec6d02f72d568d0d6c0ae0869cf393 Mon Sep 17 00:00:00 2001 From: Luca Frosini Date: Tue, 16 Nov 2021 18:57:05 +0100 Subject: [PATCH] Implementing moderation --- .../gcat/persistence/ckan/CKANPackage.java | 329 +++++++++++------- 1 file changed, 208 insertions(+), 121 deletions(-) diff --git a/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackage.java b/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackage.java index 172e908..a17b234 100644 --- a/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackage.java +++ b/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackage.java @@ -120,6 +120,8 @@ public class CKANPackage extends CKAN { protected final CKANInstance ckanInstance; protected final Set supportedOrganizations; + protected String moderationMessage; + public CKANPackage() { super(); @@ -615,7 +617,7 @@ public class CKANPackage extends CKAN { } } - protected CMItemStatus getCMItemStatus() { + protected CMItemStatus getCMItemStatus() throws Exception { String cmItemStatusString = CMItemStatus.APPROVED.getValue(); boolean found = false; @@ -633,9 +635,12 @@ public class CKANPackage extends CKAN { CMItemStatus cmItemStatus = CMItemStatus.getCMItemStatusFromValue(cmItemStatusString); if(!found) { - // TODO can be used to fix an item published before activating the moderation. - // The item is considered ad approved and the item representation must be updated - return cmItemStatus; + // The item was published before activating the moderation. + // The item is considered as approved and the item representation must be updated + setToApproved(result); + String ret = sendPostRequest(ITEM_PATCH, getAsString(result)); + result = mapper.readTree(ret); + result = cleanResult(result); } return cmItemStatus; @@ -703,40 +708,6 @@ public class CKANPackage extends CKAN { ((ObjectNode) jsonNode).put(SEARCHABLE_KEY, false); } - protected void setToApproved(JsonNode jsonNode) { - ArrayNode extras = (ArrayNode) jsonNode.get(EXTRAS_KEY); - - boolean approvedSet = false; - CMItemVisibility cmItemVisibility = null; - - for(JsonNode extra : extras) { - if(extra.has(EXTRAS_KEY_KEY) && extra.get(EXTRAS_KEY_KEY).asText().compareTo(GCatConstants.SYSTEM_CM_ITEM_STATUS) == 0) { - ((ObjectNode) extra).put(EXTRAS_VALUE_KEY, CMItemStatus.APPROVED.getValue()); - approvedSet = true; - } - - if(extra.has(EXTRAS_KEY_KEY) && extra.get(EXTRAS_KEY_KEY).asText().compareTo(GCatConstants.SYSTEM_CM_ITEM_VISIBILITY) == 0) { - cmItemVisibility = CMItemVisibility.getCMItemStatusFromValue(extra.get(EXTRAS_VALUE_KEY).asText()); - } - } - - - - if(!approvedSet) { - addExtraField(jsonNode, GCatConstants.SYSTEM_CM_ITEM_STATUS, CMItemStatus.APPROVED.getValue()); - } - - if(cmItemVisibility==null) { - cmItemVisibility = CMItemVisibility.PUBLIC; - addExtraField(jsonNode, GCatConstants.SYSTEM_CM_ITEM_VISIBILITY, cmItemVisibility.getValue()); - } - - - ((ObjectNode) jsonNode).put(PRIVATE_KEY, cmItemVisibility == CMItemVisibility.RESTRICTED ? true :false); - ((ObjectNode) jsonNode).put(SEARCHABLE_KEY, true); - } - - // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.create.package_create @Override public String create(String json) { @@ -777,9 +748,6 @@ public class CKANPackage extends CKAN { ArrayNode created = createResources(resourcesToBeCreated); ((ObjectNode) result).replace(RESOURCES_KEY, created); - // Adding Item URL via Resolver as - // ((ObjectNode) result).put(ITEM_URL_KEY, catalogueItemURL); - // Actions performed after a package has been correctly created on ckan. String title = result.get(TITLE_KEY).asText(); @@ -799,53 +767,6 @@ public class CKANPackage extends CKAN { } } - protected JsonNode checkModerationUpdate(JsonNode jsonNode){ - PortalUser portalUser = ckanUser.getPortalUser(); - - if(isModerationEnabled()) { - CMItemStatus cmItemStatus = getCMItemStatus(); - - boolean setToPending = true; - - switch (cmItemStatus) { - case APPROVED: - if(ckanUser.getRole() != Role.ADMIN) { - throw new ForbiddenException("Only " + Role.ADMIN.getPortalRole() + "s are entitled to update an " + cmItemStatus.getValue() + " item"); - } - setToPending = false; - break; - - case PENDING: - if(result.get(AUTHOR_EMAIL_KEY).asText().compareTo(portalUser.getEMail())==0) { - break; - } - if(portalUser.isCatalogueModerator()) { - break; - } - throw new ForbiddenException("You are not entitled to update a " + cmItemStatus.getValue() + " item"); - - case REJECTED: - if(result.get(AUTHOR_EMAIL_KEY).asText().compareTo(portalUser.getEMail())==0) { - break; - } - if(ckanUser.getRole() == Role.ADMIN || portalUser.isCatalogueModerator()) { - break; - } - throw new ForbiddenException("You are not entitled to update a " + cmItemStatus.getValue() + " item"); - - default: - break; - } - - if(setToPending) { - setToPending(jsonNode); - } - - } - - return jsonNode; - } - // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.update.package_update @Override public String update(String json) { @@ -903,12 +824,6 @@ public class CKANPackage extends CKAN { ckanResource.deleteFile(); } - /* - // Adding Item URL via Resolver - URIResolver uriResolver = new URIResolver(); - String catalogueItemURL = uriResolver.getCatalogueItemURL(name); - ((ObjectNode) result).put(ITEM_URL_KEY, catalogueItemURL); - */ result = cleanResult(result); return getAsString(result); @@ -921,26 +836,6 @@ public class CKANPackage extends CKAN { } } - public String approve() { - try { - read(); - - if(isModerationEnabled()) { - setToApproved(result); - } else { - throw new MethodNotSupportedException("The approve operation is available only in moderation mode"); - } - - result = cleanResult(result); - - return getAsString(result); - }catch(WebApplicationException e) { - throw e; - } catch(Exception e) { - throw new InternalServerErrorException(e); - } - } - // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.patch.package_patch @Override public String patch(String json) { @@ -1000,13 +895,6 @@ public class CKANPackage extends CKAN { ckanResource.deleteFile(); } - /* - // Adding Item URL via Resolver - URIResolver uriResolver = new URIResolver(); - String catalogueItemURL = uriResolver.getCatalogueItemURL(name); - ((ObjectNode) result).put(ITEM_URL_KEY, catalogueItemURL); - */ - result = cleanResult(result); return getAsString(result); @@ -1053,4 +941,203 @@ public class CKANPackage extends CKAN { super.purge(); } + /** + * Used for bulk purging. Internal use only + */ + protected void purgeNoCheckNoDeleteFiles() { +// setApiKey(CKANUtility.getSysAdminAPI()); +// super.purge(); + } + + // Moderation Related functions + + protected JsonNode checkModerationUpdate(JsonNode jsonNode) throws Exception{ + PortalUser portalUser = ckanUser.getPortalUser(); + + if(isModerationEnabled()) { + CMItemStatus cmItemStatus = getCMItemStatus(); + + boolean setToPending = true; + + switch (cmItemStatus) { + case APPROVED: + if(ckanUser.getRole() != Role.ADMIN) { + throw new ForbiddenException("Only " + Role.ADMIN.getPortalRole() + "s are entitled to update an " + cmItemStatus.getValue() + " item"); + } + setToApproved(jsonNode); + setToPending = false; + break; + + case PENDING: + if(result.get(AUTHOR_EMAIL_KEY).asText().compareTo(portalUser.getEMail())==0) { + break; + } + if(portalUser.isCatalogueModerator()) { + break; + } + throw new ForbiddenException("You are not entitled to update a " + cmItemStatus.getValue() + " item"); + + case REJECTED: + if(result.get(AUTHOR_EMAIL_KEY).asText().compareTo(portalUser.getEMail())==0) { + break; + } + if(ckanUser.getRole() == Role.ADMIN || portalUser.isCatalogueModerator()) { + break; + } + throw new ForbiddenException("You are not entitled to update a " + cmItemStatus.getValue() + " item"); + + default: + break; + } + + if(setToPending) { + setToPending(jsonNode); + } + + } + + return jsonNode; + } + + + public void setModerationMessage(String moderationMessage) { + this.moderationMessage = moderationMessage; + } + + protected void setToRejected(JsonNode jsonNode) { + addExtraField(jsonNode, GCatConstants.SYSTEM_CM_ITEM_STATUS, CMItemStatus.REJECTED.getValue()); + } + + + protected void setToApproved(JsonNode jsonNode) { + ArrayNode extras = (ArrayNode) jsonNode.get(EXTRAS_KEY); + + boolean approvedSet = false; + CMItemVisibility cmItemVisibility = null; + + for(JsonNode extra : extras) { + if(extra.has(EXTRAS_KEY_KEY) && extra.get(EXTRAS_KEY_KEY).asText().compareTo(GCatConstants.SYSTEM_CM_ITEM_STATUS) == 0) { + ((ObjectNode) extra).put(EXTRAS_VALUE_KEY, CMItemStatus.APPROVED.getValue()); + approvedSet = true; + } + + if(extra.has(EXTRAS_KEY_KEY) && extra.get(EXTRAS_KEY_KEY).asText().compareTo(GCatConstants.SYSTEM_CM_ITEM_VISIBILITY) == 0) { + cmItemVisibility = CMItemVisibility.getCMItemStatusFromValue(extra.get(EXTRAS_VALUE_KEY).asText()); + } + } + + + + if(!approvedSet) { + addExtraField(jsonNode, GCatConstants.SYSTEM_CM_ITEM_STATUS, CMItemStatus.APPROVED.getValue()); + } + + if(cmItemVisibility==null) { + cmItemVisibility = CMItemVisibility.PUBLIC; + addExtraField(jsonNode, GCatConstants.SYSTEM_CM_ITEM_VISIBILITY, cmItemVisibility.getValue()); + } + + + ((ObjectNode) jsonNode).put(PRIVATE_KEY, cmItemVisibility == CMItemVisibility.RESTRICTED ? true :false); + ((ObjectNode) jsonNode).put(SEARCHABLE_KEY, true); + } + + public String approve() { + try { + if(isModerationEnabled()) { + String ret = read(); + + CMItemStatus cmItemStatus = getCMItemStatus(); + switch (cmItemStatus) { + case APPROVED: + // Nothing TO DO + break; + + case REJECTED: + throw new MethodNotSupportedException("You can't approve a rejected item. The item must be updated first. The update will set the item in pending, than it can be approved/rejected."); + + case PENDING: + if(ckanUser.getRole() != Role.ADMIN) { + throw new MethodNotSupportedException("Only catalogue moderator can approve a pending item."); + } + setToApproved(result); + ret = sendPostRequest(ITEM_PATCH, getAsString(result)); + break; + + default: + break; + } + + result = mapper.readTree(ret); + result = cleanResult(result); + + return getAsString(result); + + } + + throw new MethodNotSupportedException("The approve operation is available only in moderation mode"); + + }catch(WebApplicationException e) { + throw e; + } catch(Exception e) { + throw new InternalServerErrorException(e); + } + } + + public String reject() { + try { + if(isModerationEnabled()) { + String ret = read(); + + CMItemStatus cmItemStatus = getCMItemStatus(); + switch (cmItemStatus) { + case APPROVED: + throw new MethodNotSupportedException("You can't rejected an approved item. The item must be updated first. The update will set the item in pending, than it can be approved/rejected."); + + case REJECTED: + // Nothing TO DO + break; + + case PENDING: + if(ckanUser.getRole() != Role.ADMIN) { + throw new MethodNotSupportedException("Only catalogue moderator can reject a pending item."); + } + setToRejected(result); + ret = sendPostRequest(ITEM_PATCH, getAsString(result)); + break; + + default: + break; + } + + result = mapper.readTree(ret); + result = cleanResult(result); + + return getAsString(result); + + } + + throw new MethodNotSupportedException("The reject operation is available only in moderation mode"); + + }catch(WebApplicationException e) { + throw e; + } catch(Exception e) { + throw new InternalServerErrorException(e); + } + } + + public void message() { + try { + if(isModerationEnabled()) { + // TODO + } + throw new MethodNotSupportedException("The message operation is available only in moderation mode"); + }catch(WebApplicationException e) { + throw e; + } catch(Exception e) { + throw new InternalServerErrorException(e); + } + } + + }