diff --git a/CHANGELOG.md b/CHANGELOG.md
index 24583d0..e9967e1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,11 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
# Changelog for gCube Catalogue (gCat) Service
+## [v2.3.0-SNAPSHOT]
+
+- Added moderation link in moderation message [#23142]
+- Switched moderation messages to notification [#23317]
+
## [v2.2.0]
- Switched gcat credentials to new IAM authz [#21628][#22727]
diff --git a/pom.xml b/pom.xml
index bd4bb0e..08e11ab 100644
--- a/pom.xml
+++ b/pom.xml
@@ -12,7 +12,7 @@
org.gcube.data-catalogue
gcat
war
- 2.2.0
+ 2.3.0-SNAPSHOT
gCube Catalogue (gCat) Service
This service allows any client to publish on the gCube Catalogue.
@@ -64,11 +64,11 @@
gcat-api
[2.0.0,3.0.0-SNAPSHOT)
-
-
-
-
-
+
+ org.gcube.social-networking
+ social-service-client
+ 1.1.0-SNAPSHOT
+
org.gcube.common
authorization-utils
@@ -227,12 +227,6 @@
${enunciate.version}
provided
-
- org.geotoolkit
- geotk-xml-base
- 3.20-geoapi-3.0
- provided
-
javax.servlet
javax.servlet-api
diff --git a/src/main/java/org/gcube/gcat/moderation/thread/ModerationThread.java b/src/main/java/org/gcube/gcat/moderation/thread/ModerationThread.java
index 0be68b4..e66881e 100644
--- a/src/main/java/org/gcube/gcat/moderation/thread/ModerationThread.java
+++ b/src/main/java/org/gcube/gcat/moderation/thread/ModerationThread.java
@@ -1,9 +1,18 @@
package org.gcube.gcat.moderation.thread;
+import java.util.HashMap;
+import java.util.Map;
+
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
+import org.gcube.common.authorization.utils.manager.SecretManager;
+import org.gcube.common.authorization.utils.manager.SecretManagerProvider;
+import org.gcube.gcat.api.configuration.CatalogueConfiguration;
import org.gcube.gcat.api.moderation.CMItemStatus;
-import org.gcube.gcat.moderation.thread.social.SocialMessageModerationThread;
+import org.gcube.gcat.moderation.thread.social.notifications.SocialNotificationModerationThread;
import org.gcube.gcat.persistence.ckan.CKANUser;
+import org.gcube.portlets.user.uriresolvermanager.UriResolverManager;
+import org.gcube.portlets.user.uriresolvermanager.resolvers.query.CatalogueResolverQueryString.MODERATION_OP;
+import org.gcube.portlets.user.uriresolvermanager.resolvers.query.CatalogueResolverQueryStringBuilder;
/**
* @author Luca Frosini (ISTI - CNR)
@@ -14,6 +23,8 @@ public abstract class ModerationThread {
protected String itemName;
protected String itemTitle;
protected String itemURL;
+
+ protected String moderationURL;
protected boolean create;
protected CMItemStatus cmItemStatus;
@@ -24,14 +35,15 @@ public abstract class ModerationThread {
public static ModerationThread getDefaultInstance() {
// return new FakeModerationThread();
- return new SocialMessageModerationThread();
+ // return new SocialMessageModerationThread();
+ return new SocialNotificationModerationThread();
}
public ModerationThread() {
this.objectMapper = new ObjectMapper();
this.itemAuthor = false;
this.create = false;
- cmItemStatus = CMItemStatus.PENDING;
+ this.cmItemStatus = CMItemStatus.PENDING;
}
public void setItemCoordinates(String itemID, String itemName, String itemTitle, String itemURL) {
@@ -49,6 +61,32 @@ public abstract class ModerationThread {
this.ckanUser = ckanUser;
}
+ public String getModerationURL() {
+ if(moderationURL==null) {
+ try {
+ SecretManager secretManager = SecretManagerProvider.instance.get();
+ String context = secretManager.getContext();
+ UriResolverManager resolver = new UriResolverManager("CTLG");
+ Map params = new HashMap();
+ params.put("gcube_scope", context); //e.g. /gcube/devsec/devVRE
+ params.put("entity_context", "organization");
+ params.put("entity_name", CatalogueConfiguration.getOrganizationName(context)); //e.g. devvre
+
+ CatalogueResolverQueryStringBuilder builder = new CatalogueResolverQueryStringBuilder(itemName); //item name under moderation
+ builder.itemStatus(cmItemStatus.name()). //e.g. pending, approved, rejected
+ moderation(MODERATION_OP.show);
+
+ String queryString = builder.buildQueryParametersToQueryString();
+ params.put(CatalogueResolverQueryStringBuilder.QUERY_STRING_PARAMETER, queryString);
+
+ moderationURL = resolver.getLink(params, true);
+ }catch (Exception e) {
+ return itemURL;
+ }
+ }
+ return moderationURL;
+ }
+
/**
* The message is sent as gCat
* @param message
diff --git a/src/main/java/org/gcube/gcat/social/Message.java b/src/main/java/org/gcube/gcat/moderation/thread/social/messages/Message.java
similarity index 96%
rename from src/main/java/org/gcube/gcat/social/Message.java
rename to src/main/java/org/gcube/gcat/moderation/thread/social/messages/Message.java
index a5daf87..326a2fc 100644
--- a/src/main/java/org/gcube/gcat/social/Message.java
+++ b/src/main/java/org/gcube/gcat/moderation/thread/social/messages/Message.java
@@ -1,4 +1,4 @@
-package org.gcube.gcat.social;
+package org.gcube.gcat.moderation.thread.social.messages;
import java.util.ArrayList;
import java.util.Collection;
diff --git a/src/main/java/org/gcube/gcat/moderation/thread/social/messages/SocialMessage.java b/src/main/java/org/gcube/gcat/moderation/thread/social/messages/SocialMessage.java
new file mode 100644
index 0000000..cec279c
--- /dev/null
+++ b/src/main/java/org/gcube/gcat/moderation/thread/social/messages/SocialMessage.java
@@ -0,0 +1,98 @@
+package org.gcube.gcat.moderation.thread.social.messages;
+
+import java.net.HttpURLConnection;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+
+import org.gcube.com.fasterxml.jackson.databind.JsonNode;
+import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
+import org.gcube.common.authorization.utils.manager.SecretManager;
+import org.gcube.common.authorization.utils.manager.SecretManagerProvider;
+import org.gcube.common.authorization.utils.socialservice.SocialService;
+import org.gcube.common.gxhttp.request.GXHTTPStringRequest;
+import org.gcube.gcat.utils.Constants;
+import org.gcube.gcat.utils.HTTPUtility;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Luca Frosini (ISTI - CNR)
+ */
+public class SocialMessage extends Thread {
+
+ private static final Logger logger = LoggerFactory.getLogger(SocialMessage.class);
+
+ public static final String ITEM_URL = "Item URL";
+
+ // https://wiki.gcube-system.org/gcube/Social_Networking_Service#Send_a_message
+ protected static final String SOCIAL_SERVICE_SEND_MESSAGE_PATH = "/2/messages/write-message";
+
+ protected static final String RESPONSE_SUCCESS_KEY = "success";
+ protected static final String RESPONSE_MESSAGE_KEY = "message";
+
+ protected final ObjectMapper objectMapper;
+
+ protected Message message;
+
+ public SocialMessage() throws Exception {
+ super();
+ this.objectMapper = new ObjectMapper();
+ }
+
+ public Message getMessage() {
+ return message;
+ }
+
+ public void setMessage(Message message) {
+ this.message = message;
+ }
+
+ @Override
+ public void run() {
+
+ try {
+ logger.info("Going to send Message {}", message);
+ // write message
+ sendSocialMessage();
+ } catch(Exception e) {
+ logger.error("Error while executing post creation actions", e);
+ }
+ }
+
+ public void sendSocialMessage() {
+
+ try {
+ String basePath = SocialService.getSocialService().getServiceBasePath();
+ if(basePath == null) {
+ logger.info("Unable to send a message because there is no social networking service available");
+ return;
+ }
+ basePath = basePath.endsWith("/") ? basePath : basePath + "/";
+
+ String messageString = objectMapper.writeValueAsString(message);
+ logger.debug("The message that is going to be send is\n{}", messageString);
+
+ GXHTTPStringRequest gxhttpStringRequest = GXHTTPStringRequest.newRequest(basePath);
+ gxhttpStringRequest.from(Constants.CATALOGUE_NAME);
+ gxhttpStringRequest.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
+ SecretManager secretManager = SecretManagerProvider.instance.get();
+ gxhttpStringRequest.setSecurityToken(secretManager.getCurrentSecretHolder().getSecrets().first().getToken());
+ gxhttpStringRequest.path(SOCIAL_SERVICE_SEND_MESSAGE_PATH);
+
+ HttpURLConnection httpURLConnection = gxhttpStringRequest.post(messageString);
+ String ret = HTTPUtility.getResultAsString(httpURLConnection);
+ JsonNode jsonNode = objectMapper.readTree(ret);
+ if(jsonNode.get(RESPONSE_SUCCESS_KEY).asBoolean()) {
+ logger.info("Message sent : {}", messageString);
+ } else {
+ logger.info("Failed to write the message {}. Reason {}", messageString,
+ jsonNode.get(RESPONSE_MESSAGE_KEY).asText());
+ }
+ } catch(Exception e) {
+ logger.error("Unable to send the message : " + message.toString(), e);
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/gcube/gcat/moderation/thread/social/SocialMessageModerationThread.java b/src/main/java/org/gcube/gcat/moderation/thread/social/messages/SocialMessageModerationThread.java
similarity index 97%
rename from src/main/java/org/gcube/gcat/moderation/thread/social/SocialMessageModerationThread.java
rename to src/main/java/org/gcube/gcat/moderation/thread/social/messages/SocialMessageModerationThread.java
index fc3eb3a..2db8759 100644
--- a/src/main/java/org/gcube/gcat/moderation/thread/social/SocialMessageModerationThread.java
+++ b/src/main/java/org/gcube/gcat/moderation/thread/social/messages/SocialMessageModerationThread.java
@@ -1,4 +1,4 @@
-package org.gcube.gcat.moderation.thread.social;
+package org.gcube.gcat.moderation.thread.social.messages;
import java.io.StringWriter;
import java.util.Set;
@@ -9,8 +9,6 @@ import org.gcube.common.authorization.utils.secret.Secret;
import org.gcube.gcat.api.moderation.CMItemStatus;
import org.gcube.gcat.api.moderation.Moderated;
import org.gcube.gcat.moderation.thread.ModerationThread;
-import org.gcube.gcat.social.Message;
-import org.gcube.gcat.social.SocialMessage;
import org.gcube.gcat.social.SocialUsers;
import org.gcube.gcat.utils.Constants;
import org.slf4j.Logger;
@@ -37,7 +35,11 @@ public class SocialMessageModerationThread extends ModerationThread {
stringBuffer.append(itemID);
stringBuffer.append("\n");
stringBuffer.append("URL: ");
- stringBuffer.append(itemURL);
+ if(cmItemStatus == CMItemStatus.APPROVED) {
+ stringBuffer.append(itemURL);
+ }else {
+ stringBuffer.append(getModerationURL());
+ }
stringBuffer.append("\n\n");
return stringBuffer;
}
@@ -197,3 +199,4 @@ public class SocialMessageModerationThread extends ModerationThread {
}
}
+
\ No newline at end of file
diff --git a/src/main/java/org/gcube/gcat/moderation/thread/social/notifications/SocialNotificationModerationThread.java b/src/main/java/org/gcube/gcat/moderation/thread/social/notifications/SocialNotificationModerationThread.java
new file mode 100644
index 0000000..b406b65
--- /dev/null
+++ b/src/main/java/org/gcube/gcat/moderation/thread/social/notifications/SocialNotificationModerationThread.java
@@ -0,0 +1,297 @@
+package org.gcube.gcat.moderation.thread.social.notifications;
+
+import java.net.URL;
+import java.util.Set;
+
+import org.gcube.common.authorization.utils.manager.SecretManager;
+import org.gcube.common.authorization.utils.manager.SecretManagerProvider;
+import org.gcube.common.authorization.utils.secret.Secret;
+import org.gcube.gcat.api.moderation.CMItemStatus;
+import org.gcube.gcat.api.moderation.Moderated;
+import org.gcube.gcat.moderation.thread.ModerationThread;
+import org.gcube.gcat.persistence.ckan.CKANUser;
+import org.gcube.gcat.social.SocialUsers;
+import org.gcube.gcat.utils.Constants;
+import org.gcube.social_networking.social_networking_client_library.NotificationClient;
+import org.gcube.social_networking.socialnetworking.model.beans.catalogue.CatalogueEvent;
+import org.gcube.social_networking.socialnetworking.model.beans.catalogue.CatalogueEventType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Luca Frosini (ISTI - CNR)
+ */
+public class SocialNotificationModerationThread extends ModerationThread {
+
+ private static final Logger logger = LoggerFactory.getLogger(SocialNotificationModerationThread.class);
+
+ public static final String AUTHOR = "Author";
+
+ protected CatalogueEventType catalogueEventType;
+ protected boolean comment;
+
+ protected static final boolean notificationSentByGCat;
+
+ static {
+ notificationSentByGCat = false;
+ }
+
+ public SocialNotificationModerationThread() {
+ super();
+ this.comment = false;
+ }
+
+ /**
+ * Create the message for an item that is created/updated
+ */
+ protected void notifyItemToBeManaged() throws Exception {
+ /*
+ * An example of created message is:
+ *
+ * [mister x] created/updated the item "[TITLE]". You are kindly requested to review it and decide either to APPROVE or REJECT it. [Go to catalogue]
+ *
+ */
+ String fullName = ckanUser.getNameSurname();
+ StringBuffer stringBuffer = new StringBuffer();
+ if(notificationSentByGCat) {
+ stringBuffer.append(fullName);
+ }
+ stringBuffer.append(create ? " created " : " updated ");
+ stringBuffer.append("the item ");
+ stringBuffer = addQuotedTitle(stringBuffer);
+ stringBuffer.append(". You are kindly requested to review it and decide either to APPROVE or REJECT it. ");
+ postMessage(stringBuffer.toString());
+ }
+
+
+ public void postItemCreated() throws Exception {
+ create = true;
+ cmItemStatus = CMItemStatus.PENDING;
+ catalogueEventType = CatalogueEventType.ITEM_SUBMITTED;
+ notifyItemToBeManaged();
+ }
+
+ public void postItemUpdated() throws Exception {
+ create = false;
+ cmItemStatus = CMItemStatus.PENDING;
+ catalogueEventType = CatalogueEventType.ITEM_UPDATED;
+ notifyItemToBeManaged();
+ }
+
+ protected StringBuffer addUserWithRole(String fullName, String role, StringBuffer stringBuffer, boolean addUserFullName) {
+ if(addUserFullName) {
+ stringBuffer.append(fullName);
+ }
+ if(role!=null) {
+ stringBuffer.append(" [");
+ stringBuffer.append(role);
+ stringBuffer.append("] ");
+ }
+ return stringBuffer;
+ }
+
+ protected StringBuffer addUserWithRole(String fullName, String role, StringBuffer stringBuffer) {
+ return addUserWithRole(fullName, role, stringBuffer, notificationSentByGCat);
+ }
+
+ public void postItemManaged(String userMessage) throws Exception {
+ /*
+ * [mister x] rejected the item "[TITLE]" with this accompanying message "[MESSAGE]". To resubmit it [Go to catalogue]
+ *
+ * [mister x] approved the item "[TITLE]" with this accompanying message "[MESSAGE]". [Go to catalogue]
+ */
+ create = false;
+ String fullName = ckanUser.getNameSurname();
+ StringBuffer stringBuffer = new StringBuffer();
+ stringBuffer = addUserWithRole(fullName, Moderated.CATALOGUE_MODERATOR, stringBuffer);
+ stringBuffer.append(cmItemStatus.getValue());
+ stringBuffer.append(" the item ");
+ stringBuffer = addQuotedTitle(stringBuffer);
+ if(userMessage!=null && userMessage.length()>0) {
+ stringBuffer.append(" with this accompanying message \"");
+ stringBuffer.append(userMessage);
+ stringBuffer.append("\"");
+ }
+ stringBuffer.append(".");
+
+ if(cmItemStatus == CMItemStatus.REJECTED) {
+ stringBuffer.append(" To resubmit it ");
+ }
+ postMessage(stringBuffer.toString());
+ }
+
+ @Override
+ public void postItemRejected(String userMessage) throws Exception {
+ create = false;
+ cmItemStatus = CMItemStatus.REJECTED;
+ catalogueEventType = CatalogueEventType.ITEM_REJECTED;
+ postItemManaged(userMessage);
+ }
+
+ @Override
+ public void postItemApproved(String userMessage) throws Exception {
+ create = false;
+ cmItemStatus = CMItemStatus.APPROVED;
+ catalogueEventType = CatalogueEventType.ITEM_PUBLISHED;
+ postItemManaged(userMessage);
+ }
+
+ protected StringBuffer addQuotedTitle(StringBuffer stringBuffer, String quotingCharacter) {
+ stringBuffer.append(quotingCharacter);
+ stringBuffer.append(itemTitle);
+ stringBuffer.append(quotingCharacter);
+ return stringBuffer;
+ }
+
+ protected StringBuffer addQuotedTitle(StringBuffer stringBuffer) {
+ return addQuotedTitle(stringBuffer, "\"");
+ }
+
+ protected String getSubject() {
+ StringBuffer stringBuffer = new StringBuffer();
+ String fullName = ckanUser.getNameSurname();
+ if(!comment) {
+ switch (catalogueEventType) {
+ case ITEM_SUBMITTED:
+ stringBuffer.append(fullName);
+ stringBuffer.append(" created the item ");
+ break;
+
+ case ITEM_UPDATED:
+ stringBuffer.append(fullName);
+ stringBuffer.append(" updated the item ");
+ break;
+
+ case ITEM_REJECTED:
+ case ITEM_PUBLISHED:
+ addUserWithRole(fullName, Moderated.CATALOGUE_MODERATOR, stringBuffer, true);
+ stringBuffer.append(cmItemStatus.getValue());
+ stringBuffer.append(" the item ");
+ break;
+
+ default:
+ break;
+ }
+ }else {
+ addUserWithRole(fullName, itemAuthor ? SocialNotificationModerationThread.AUTHOR : Moderated.CATALOGUE_MODERATOR, stringBuffer, true);
+ stringBuffer.append("commented on the item ");
+ }
+ stringBuffer = addQuotedTitle(stringBuffer);
+ return stringBuffer.toString();
+ }
+
+ protected CatalogueEvent getCatalogueEvent(String messageString) throws Exception {
+ CatalogueEvent catalogueEvent = new CatalogueEvent();
+ catalogueEvent.setType(catalogueEventType);
+ catalogueEvent.setNotifyText(messageString);
+ catalogueEvent.setItemId(getSubject());
+ if(cmItemStatus == CMItemStatus.APPROVED) {
+ catalogueEvent.setItemURL(new URL(itemURL));
+ }else {
+ catalogueEvent.setItemURL(new URL(getModerationURL()));
+ }
+
+ Set users = SocialUsers.getUsernamesByRole(Moderated.CATALOGUE_MODERATOR);
+ users.add("luca.frosini");
+
+ SecretManager secretManager = SecretManagerProvider.instance.get();
+ String username = secretManager.getUser().getUsername();
+ // Adding the user is generating the event
+ users.add(username);
+ // Adding item creator
+ users.add(CKANUser.getUsernameFromCKANUsername(ckanUser.getName()));
+
+ catalogueEvent.setIdsToNotify(users.toArray(new String[users.size()]));
+ catalogueEvent.setIdsAsGroup(false);
+
+ return catalogueEvent;
+ }
+
+ @Override
+ protected void postMessage(String messageString) throws Exception {
+ CatalogueEvent catalogueEvent = getCatalogueEvent(messageString);
+ SecretManager secretManager = SecretManagerProvider.instance.get();
+ Secret secret = Constants.getCatalogueSecret();
+ if(notificationSentByGCat) {
+ secretManager.startSession(secret);
+ }
+ try {
+ sendNotification(catalogueEvent);
+ }finally {
+ if(notificationSentByGCat) {
+ secretManager.endSession();
+ }
+ }
+ }
+
+ @Override
+ public void postUserMessage(CMItemStatus cmItemStatus, String userMessage) throws Exception {
+ /*
+ * [mister x] ([Role]) commented on the item "[TITLE]" as follows "[MESSAGE]". [Go to catalogue]
+ */
+ this.create = false;
+ this.cmItemStatus = cmItemStatus;
+ this.comment = true;
+
+ switch (cmItemStatus) {
+ case PENDING:
+ catalogueEventType = CatalogueEventType.ITEM_UPDATED;
+ break;
+
+ case APPROVED:
+ catalogueEventType = CatalogueEventType.ITEM_PUBLISHED;
+ break;
+
+ case REJECTED:
+ catalogueEventType = CatalogueEventType.ITEM_REJECTED;
+ break;
+
+ default:
+ break;
+ }
+
+ String fullName = ckanUser.getNameSurname();
+ StringBuffer stringBuffer = new StringBuffer();
+ stringBuffer = addUserWithRole(fullName, itemAuthor ? SocialNotificationModerationThread.AUTHOR : Moderated.CATALOGUE_MODERATOR, stringBuffer);
+ stringBuffer.append("commented on the item ");
+ stringBuffer = addQuotedTitle(stringBuffer);
+ stringBuffer.append(" as follows \"");
+ stringBuffer.append(userMessage);
+ stringBuffer.append("\".");
+ CatalogueEvent catalogueEvent = getCatalogueEvent(stringBuffer.toString());
+ SecretManager secretManager = SecretManagerProvider.instance.get();
+ Secret secret = Constants.getCatalogueSecret();
+ if(notificationSentByGCat) {
+ secretManager.startSession(secret);
+ }
+ try {
+ sendNotification(catalogueEvent);
+ }finally {
+ if(notificationSentByGCat) {
+ secretManager.endSession();
+ }
+ }
+ }
+
+ protected void sendNotification(CatalogueEvent catalogueEvent) throws Exception {
+ Thread thread = new Thread() {
+ public void run() {
+ try {
+ NotificationClient nc = new NotificationClient();
+ nc.sendCatalogueEvent(catalogueEvent);
+ } catch(Exception e) {
+ logger.error("Error while sending notification.", e);
+ }
+ }
+ };
+ thread.run();
+ // thread.start();
+ }
+
+ @Override
+ protected void createModerationThread() throws Exception {
+ create = true;
+ cmItemStatus = CMItemStatus.PENDING;
+ }
+
+}
diff --git a/src/main/java/org/gcube/gcat/persistence/ckan/CKAN.java b/src/main/java/org/gcube/gcat/persistence/ckan/CKAN.java
index 8190dc8..493b2af 100644
--- a/src/main/java/org/gcube/gcat/persistence/ckan/CKAN.java
+++ b/src/main/java/org/gcube/gcat/persistence/ckan/CKAN.java
@@ -360,7 +360,7 @@ public abstract class CKAN {
}
}
- protected void purge() {
+ public void purge() {
sendPostRequest(PURGE, createJsonNodeWithNameAsID());
}
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 82d6e3d..b221991 100644
--- a/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackage.java
+++ b/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackage.java
@@ -67,9 +67,9 @@ public class CKANPackage extends CKAN implements Moderated {
// limit in https://docs.ckan.org/en/latest/api/index.html#ckan.logic.action.get.package_search
- protected static final String ROWS_KEY = "rows";
+ public static final String ROWS_KEY = "rows";
// offset in https://docs.ckan.org/en/latest/api/index.html#ckan.logic.action.get.package_search
- protected static final String START_KEY = "start";
+ public static final String START_KEY = "start";
protected static final String ORGANIZATION_FILTER_TEMPLATE = GCatConstants.ORGANIZATION_PARAMETER + ":%s";
@@ -983,9 +983,9 @@ public class CKANPackage extends CKAN implements Moderated {
/**
* Used for bulk purging. Internal use only
*/
- protected void purgeNoCheckNoDeleteFiles() {
-// setApiKey(CKANUtility.getSysAdminAPI());
-// super.purge();
+ public void purgeNoCheckNoDeleteFiles() {
+ setApiKey(CKANUtility.getSysAdminAPI());
+ super.purge();
}
/*
diff --git a/src/main/java/org/gcube/gcat/persistence/ckan/CKANResource.java b/src/main/java/org/gcube/gcat/persistence/ckan/CKANResource.java
index 64903db..d5743cb 100644
--- a/src/main/java/org/gcube/gcat/persistence/ckan/CKANResource.java
+++ b/src/main/java/org/gcube/gcat/persistence/ckan/CKANResource.java
@@ -471,7 +471,7 @@ public class CKANResource extends CKAN {
}
@Override
- protected void purge() {
+ public void purge() {
String[] moreAllowed = new String[] {HEAD.class.getSimpleName(), GET.class.getSimpleName(),
PUT.class.getSimpleName(), DELETE.class.getSimpleName()};
throw new NotAllowedException(OPTIONS.class.getSimpleName(), moreAllowed);
diff --git a/src/main/java/org/gcube/gcat/persistence/ckan/CKANUser.java b/src/main/java/org/gcube/gcat/persistence/ckan/CKANUser.java
index d0379a4..39b24aa 100644
--- a/src/main/java/org/gcube/gcat/persistence/ckan/CKANUser.java
+++ b/src/main/java/org/gcube/gcat/persistence/ckan/CKANUser.java
@@ -199,11 +199,20 @@ public class CKANUser extends CKAN {
}
protected static String getCKANUsername(String username) {
- if(username == null)
+ if(username == null) {
return null;
+ }
return username.trim().replaceAll("\\.", "_");
}
+ public static String getUsernameFromCKANUsername(String ckanUsername) {
+ if(ckanUsername == null) {
+ return null;
+ }
+ return ckanUsername.trim().replaceAll("_", ".");
+ }
+
+
public static String getCKANUsername() {
String username = SecretManagerProvider.instance.get().getUser().getUsername();
return getCKANUsername(username);
@@ -215,7 +224,7 @@ public class CKANUser extends CKAN {
return ret;
}
- protected void addUserToOrganization(String organizationName, String ckanUsername, String role) {
+ public void addUserToOrganization(String organizationName, String ckanUsername, String role) {
logger.trace("Going to add user {} to organization {} with role {}", ckanUsername, organizationName, role);
CKANOrganization ckanOrganization = new CKANOrganization();
ckanOrganization.setApiKey(CKANUtility.getSysAdminAPI());
diff --git a/src/test/java/org/gcube/gcat/moderation/ModerationThreadTest.java b/src/test/java/org/gcube/gcat/moderation/ModerationThreadTest.java
index 1b95f88..ba5ea18 100644
--- a/src/test/java/org/gcube/gcat/moderation/ModerationThreadTest.java
+++ b/src/test/java/org/gcube/gcat/moderation/ModerationThreadTest.java
@@ -4,7 +4,6 @@ import org.gcube.gcat.ContextTest;
import org.gcube.gcat.api.moderation.CMItemStatus;
import org.gcube.gcat.moderation.thread.ModerationThread;
import org.gcube.gcat.persistence.ckan.CKANUser;
-import org.junit.Ignore;
import org.junit.Test;
/**
@@ -12,23 +11,47 @@ import org.junit.Test;
*/
public class ModerationThreadTest extends ContextTest {
- @Test
- @Ignore
- public void test() throws Exception {
+ protected ModerationThread getModerationThread(CKANUser ckanUser) {
ModerationThread moderationThread = ModerationThread.getDefaultInstance();
- moderationThread.setItemCoordinates("e31a6ba8-66ef-47b8-b61f-99a1366b4a69", "my_first_restful_transaction_model", "RESTful Transaction Model", "https://data.dev.d4science.org/ctlg/devVRE/my_first_restful_transaction_model");
+ moderationThread.setItemCoordinates("b1040e70-774f-47b6-95e9-f24efca50caf", "my_first_restful_transaction_model", "RESTful Transaction Model", "https://data.dev.d4science.org/ctlg/devVRE/my_first_restful_transaction_model");
+ moderationThread.setCKANUser(ckanUser);
+ return moderationThread;
+ }
+
+ @Test
+ // @Ignore
+ public void testModerationThread() throws Exception {
+ ContextTest.setContextByName("pasquale.pagano_/gcube/devsec/devVRE");
+
CKANUser ckanUser = new CKANUser();
ckanUser.setName(CKANUser.getCKANUsername());
ckanUser.read();
- moderationThread.setCKANUser(ckanUser);
+
+ ModerationThread moderationThread = getModerationThread(ckanUser);
moderationThread.postItemCreated();
+
+ moderationThread = getModerationThread(ckanUser);
moderationThread.postItemUpdated();
+
+ moderationThread = getModerationThread(ckanUser);
+ moderationThread.postUserMessage(CMItemStatus.PENDING, "Pensaci Bene");
+
+ moderationThread = getModerationThread(ckanUser);
moderationThread.postItemRejected(null);
+
+ moderationThread = getModerationThread(ckanUser);
moderationThread.postItemRejected("reject con messaggio: Non mi garba");
+
+ moderationThread = getModerationThread(ckanUser);
moderationThread.postItemApproved(null);
+
+ moderationThread = getModerationThread(ckanUser);
moderationThread.postItemApproved("approve con messaggio: Ora mi garba");
+
+ moderationThread = getModerationThread(ckanUser);
moderationThread.setItemAuthor(true);
moderationThread.postUserMessage(CMItemStatus.APPROVED, "Grazie");
+
Thread.sleep(1000);
}
diff --git a/src/test/java/org/gcube/gcat/persistence/ckan/CKANPackageTest.java b/src/test/java/org/gcube/gcat/persistence/ckan/CKANPackageTest.java
index de150ff..6998e90 100644
--- a/src/test/java/org/gcube/gcat/persistence/ckan/CKANPackageTest.java
+++ b/src/test/java/org/gcube/gcat/persistence/ckan/CKANPackageTest.java
@@ -75,7 +75,7 @@ public class CKANPackageTest extends ContextTest {
logger.debug("List:\n{}", mapper.writeValueAsString(gotList));
}
- protected UriInfo getUriInfo(MultivaluedMap queryParameters) {
+ public static UriInfo getUriInfo(MultivaluedMap queryParameters) {
UriInfo uriInfo = new UriInfo() {
@Override
diff --git a/src/test/java/org/gcube/gcat/persistence/ckan/CKANUserTest.java b/src/test/java/org/gcube/gcat/persistence/ckan/CKANUserTest.java
index bd27472..1bd6dbd 100644
--- a/src/test/java/org/gcube/gcat/persistence/ckan/CKANUserTest.java
+++ b/src/test/java/org/gcube/gcat/persistence/ckan/CKANUserTest.java
@@ -1,6 +1,7 @@
package org.gcube.gcat.persistence.ckan;
import org.gcube.gcat.ContextTest;
+import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -22,6 +23,16 @@ public class CKANUserTest extends ContextTest {
return user;
}
+ @Test
+ public void getUsernameFromCkanUsername() {
+ String username = "luca.frosini";
+ String ckanUsername = CKANUser.getCKANUsername(username);
+ Assert.assertTrue(ckanUsername.compareTo("luca_frosini")==0);
+ String gotUsername = CKANUser.getUsernameFromCKANUsername(ckanUsername);
+ Assert.assertTrue(gotUsername.compareTo(username)==0);
+ }
+
+
@Test
public void list() throws Exception {
CKANUser ckanUser = getCKANUser();
diff --git a/src/test/java/org/gcube/gcat/persistence/ckan/GRSFUtilities.java b/src/test/java/org/gcube/gcat/persistence/grsf/GRSFUtilities.java
similarity index 57%
rename from src/test/java/org/gcube/gcat/persistence/ckan/GRSFUtilities.java
rename to src/test/java/org/gcube/gcat/persistence/grsf/GRSFUtilities.java
index acf5440..4ffb42b 100644
--- a/src/test/java/org/gcube/gcat/persistence/ckan/GRSFUtilities.java
+++ b/src/test/java/org/gcube/gcat/persistence/grsf/GRSFUtilities.java
@@ -1,21 +1,43 @@
-package org.gcube.gcat.persistence.ckan;
+package org.gcube.gcat.persistence.grsf;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.UriInfo;
-import org.gcube.com.fasterxml.jackson.annotation.JsonIgnore;
import org.gcube.com.fasterxml.jackson.core.JsonProcessingException;
import org.gcube.com.fasterxml.jackson.databind.JsonNode;
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode;
import org.gcube.com.fasterxml.jackson.databind.node.ObjectNode;
import org.gcube.common.authorization.client.exceptions.ObjectNotFound;
+import org.gcube.common.authorization.utils.manager.SecretManagerProvider;
+import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.gcat.ContextTest;
+import org.gcube.gcat.api.GCatConstants;
+import org.gcube.gcat.persistence.ckan.CKANGroup;
+import org.gcube.gcat.persistence.ckan.CKANGroupTest;
+import org.gcube.gcat.persistence.ckan.CKANOrganization;
+import org.gcube.gcat.persistence.ckan.CKANOrganizationTest;
+import org.gcube.gcat.persistence.ckan.CKANPackage;
+import org.gcube.gcat.persistence.ckan.CKANPackageTest;
+import org.gcube.gcat.persistence.ckan.CKANUser;
+import org.gcube.gcat.persistence.ckan.CKANUtility;
import org.junit.Assert;
+import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -25,7 +47,7 @@ import org.slf4j.LoggerFactory;
*/
public class GRSFUtilities extends ContextTest {
- private static Logger logger = LoggerFactory.getLogger(CKANGroupTest.class);
+ private static Logger logger = LoggerFactory.getLogger(GRSFUtilities.class);
public static final String PRODUCTION_GRSF = "/d4science.research-infrastructures.eu/FARM/GRSF";
public static final String PRODUCTION_GRSF_ADMIN = "/d4science.research-infrastructures.eu/FARM/GRSF_Admin";
@@ -33,17 +55,14 @@ public class GRSFUtilities extends ContextTest {
public static final String PREPROD_GRSF_PRE = "/pred4s/preprod/GRSF_Pre";
- public GRSFUtilities() throws ObjectNotFound, Exception {
- ContextTest.setContextByName(PREPROD_GRSF_PRE);
- }
-
- @Test
- public void test() throws ObjectNotFound, Exception {
- ContextTest.setContextByName(PREPROD_GRSF_PRE);
-//
+ @Before
+ public void before() throws Exception {
+// ContextTest.setContextByName(PREPROD_GRSF_PRE);
// ContextTest.setContextByName(PRODUCTION_GRSF);
// ContextTest.setContextByName(PRODUCTION_GRSF_ADMIN);
// ContextTest.setContextByName(PRODUCTION_GRSF_PRE);
+// logger.debug(SecretManagerProvider.instance.get().getUser().getUsername());
+// logger.debug(SecretManagerProvider.instance.get().getContext());
}
private void create(Set createdGroup, Map groups, String name) throws JsonProcessingException, IOException {
@@ -157,28 +176,33 @@ public class GRSFUtilities extends ContextTest {
node.put("name", getGroupId(name));
String json = objectMapper.writeValueAsString(node);
logger.info(json);
- // ckanGroupToCreate.create(json);
+ ckanGroupToCreate.create(json);
}
-
}
// @Test
public void deleteNewGRSFGroups() throws ObjectNotFound, Exception {
String sysAdminAPI = CKANUtility.getSysAdminAPI();
- String[] groupNames = new String[] {
- "GRSF", "Legacy", "Fishery", "Stock", "FIRMS", "FishSource", "RAM",
- "Catch", "Landing",
- "Abundance Level", "Abundance Level (FIRMS Standard)", "Biomass",
- "Fishing Pressure", "Fishing Pressure (FIRMS Standard)", "State and Trend",
- "FAO Stock Status Category", "Scientific Advice",
- "GRSF SDG Flag", "GRSF Traceability Flag"
- };
+// String[] groupNames = new String[] {
+// "GRSF", "Legacy", "Fishery", "Stock", "FIRMS", "FishSource", "RAM",
+// "Catch", "Landing",
+// "Abundance Level", "Abundance Level (FIRMS Standard)", "Biomass",
+// "Fishing Pressure", "Fishing Pressure (FIRMS Standard)", "State and Trend",
+// "FAO Stock Status Category", "Scientific Advice",
+// "GRSF SDG Flag", "GRSF Traceability Flag"
+// };
+//
+ List groupNames = CKANGroupTest.listGroup();
+ logger.debug(SecretManagerProvider.instance.get().getUser().getUsername());
+ logger.debug(SecretManagerProvider.instance.get().getContext());
+
for(String name : groupNames) {
CKANGroup ckanGroupToCreate = new CKANGroup();
ckanGroupToCreate.setApiKey(sysAdminAPI);
- ckanGroupToCreate.setName(getGroupId(name));
+// ckanGroupToCreate.setName(getGroupId(name));
+ ckanGroupToCreate.setName(name);
try {
- ckanGroupToCreate.purge();
+// ckanGroupToCreate.purge();
}catch (Exception e) {
}
@@ -188,26 +212,27 @@ public class GRSFUtilities extends ContextTest {
// @Test
public void associateUserToAllCKANGroupsAndOrganization() throws ObjectNotFound, Exception {
- String username = "grsf_publisher";
- // username = "luca_frosini";
- // username = "francesco_mangiacrapa";
+ String[] usernames = new String[] { "grsf_publisher", "luca_frosini", "francesco_mangiacrapa"};
String sysAdminAPI = CKANUtility.getSysAdminAPI();
List groupNames = CKANGroupTest.listGroup();
for(String groupName : groupNames) {
CKANUser ckanUser = new CKANUser();
ckanUser.setApiKey(sysAdminAPI);
- ckanUser.setName(username);
- ckanUser.addToGroup(groupName);
+ for(String username : usernames) {
+ ckanUser.setName(username);
+ ckanUser.addToGroup(groupName);
+ }
}
List orgs = CKANOrganizationTest.listOrg();
for(String org : orgs) {
CKANUser ckanUser = new CKANUser();
ckanUser.setApiKey(sysAdminAPI);
- ckanUser.addUserToOrganization(org, username, "admin");
+ for(String username : usernames) {
+ ckanUser.addUserToOrganization(org, username, "admin");
+ }
}
-
}
// @Test
@@ -236,13 +261,122 @@ public class GRSFUtilities extends ContextTest {
}
+ protected void printLine(File file, String line) throws Exception {
+ try (FileWriter fw = new FileWriter(file, true);
+ BufferedWriter bw = new BufferedWriter(fw);
+ PrintWriter out = new PrintWriter(bw)) {
+ out.println(line);
+ out.flush();
+ } catch (IOException e) {
+ throw e;
+ }
+ }
+
+
+ public Map getListParameter(int limit, int offset, String type, String org) {
+ Map parameters = new HashMap<>();
+ if(limit <= 0) {
+ // According to CKAN documentation
+ // the number of matching rows to return. There is a hard limit of 1000 datasets per query.
+ // see https://docs.ckan.org/en/2.6/api/index.html#ckan.logic.action.get.package_search
+ limit = 1000;
+ }
+ parameters.put(CKANPackage.ROWS_KEY, String.valueOf(limit));
+
+ if(offset < 0) {
+ offset = 0;
+ }
+ parameters.put(CKANPackage.START_KEY, String.valueOf(offset));
+
+ String q = null;
+
+ if(type!=null) {
+ // This filter by type
+ StringWriter qStringWriter = new StringWriter();
+ qStringWriter.append("extras_systemtype:");
+ qStringWriter.append(type);
+ q = qStringWriter.toString();
+
+ }
+
+ if(org!=null) {
+ StringWriter qStringWriter = new StringWriter();
+ qStringWriter.append("organization:");
+ qStringWriter.append(org);
+ if(q!=null) {
+ q = q + " AND " + qStringWriter.toString();
+ }
+ }
+
+ if(q!=null) {
+ q = q + " AND (StatusoftheRecord:Approved OR StatusoftheRecord:Archived)";
+ // q = q + " AND (groups:stock-group)";
+ }
+
+
+ if(q!=null) {
+ parameters.put(GCatConstants.Q_KEY, q);
+ }
+
+
+ return parameters;
+ }
+
+ // @Test
+ public void list() throws Exception {
+ ObjectMapper mapper = new ObjectMapper();
+ int limit = 100;
+ // String[] contexts = new String[] {PRODUCTION_GRSF, PRODUCTION_GRSF_ADMIN};
+ String[] contexts = new String[] {PRODUCTION_GRSF};
+ for(String context : contexts) {
+ ContextTest.setContextByName(context);
+ logger.debug(SecretManagerProvider.instance.get().getUser().getUsername());
+ logger.debug(SecretManagerProvider.instance.get().getContext());
+ CKANPackage ckanPackage = new CKANPackage();
+ SortedSet sortedSet = new TreeSet<>();
+ String[] types = new String[] {"Marine Resource", "Assessment Unit"};
+ for(String type : types) {
+ int offset = 0;
+ boolean go = true;
+ ScopeBean scopeBean = new ScopeBean(context);
+ while(go) {
+ Map parameters = getListParameter(limit, offset==0 ? 0 : (offset*limit), type, scopeBean.name().toLowerCase());
+ String ret = ckanPackage.list(parameters);
+ JsonNode gotList = mapper.readTree(ret);
+ Assert.assertTrue(gotList instanceof ArrayNode);
+ ArrayNode itemsArray = (ArrayNode) gotList;
+ if(itemsArray.size()>0) {
+ for(JsonNode jsonNode : itemsArray) {
+ String name = jsonNode.asText();
+ sortedSet.add(name);
+ }
+ offset++;
+ }else {
+ go=false;
+ }
+ }
+ File file = new File(scopeBean.name() + "-" + type.replace(" ", "_")+".txt");
+ if(file.exists()) {
+ file.delete();
+ }
+ for(String name : sortedSet) {
+ printLine(file, name);
+ }
+ }
+ }
+ }
+
private void purgeGRSFRecords(int limit, int offset) throws Exception {
logger.debug("Going to purge {} records, starting from {}", limit, limit*offset);
CKANPackage ckanPackage = new CKANPackage();
+ MultivaluedMap mvm = new MultivaluedHashMap();
+ UriInfo uriInfo = CKANPackageTest.getUriInfo(mvm);
+ ckanPackage.setUriInfo(uriInfo);
ObjectMapper mapper = new ObjectMapper();
boolean go = true;
while(go) {
- String ret = ckanPackage.list(limit, offset);
+ Map parameters = getListParameter(limit, offset, null, null);
+ String ret = ckanPackage.list(parameters);
JsonNode gotList = mapper.readTree(ret);
Assert.assertTrue(gotList instanceof ArrayNode);
ArrayNode itemsArray = (ArrayNode) gotList;
@@ -253,21 +387,17 @@ public class GRSFUtilities extends ContextTest {
ckanPackage.setName(name);
try {
ckanPackage.purgeNoCheckNoDeleteFiles();
- if(go) {
- break;
- }
}catch (Exception e) {
- // TODO: handle exception
+ logger.error("Unable to purge record with name {}", name, e);
}
- // Thread.sleep(500);
}
+ Thread.sleep(500);
}else {
go=false;
}
}
}
- @JsonIgnore
// @Test
public void purgeAllGRSFRecords() throws Exception {
purgeGRSFRecords(100, 0);
diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml
index 4da43d9..4c2b21d 100644
--- a/src/test/resources/logback-test.xml
+++ b/src/test/resources/logback-test.xml
@@ -11,6 +11,8 @@
+
+