Implementing content moderation
This commit is contained in:
parent
e00b2010d1
commit
b31befdc8d
|
@ -255,7 +255,8 @@ public class CKANInstance {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isModerationEnabled() {
|
public boolean isModerationEnabled() {
|
||||||
return moderationEnabled;
|
return true;
|
||||||
|
// return moderationEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSysAdminToken() throws Exception {
|
public String getSysAdminToken() throws Exception {
|
||||||
|
|
|
@ -22,9 +22,13 @@ import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
import org.gcube.com.fasterxml.jackson.databind.node.ObjectNode;
|
import org.gcube.com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import org.gcube.common.scope.impl.ScopeBean;
|
import org.gcube.common.scope.impl.ScopeBean;
|
||||||
import org.gcube.common.scope.impl.ScopeBean.Type;
|
import org.gcube.common.scope.impl.ScopeBean.Type;
|
||||||
|
import org.gcube.gcat.api.CMItemStatus;
|
||||||
|
import org.gcube.gcat.api.CMItemVisibility;
|
||||||
import org.gcube.gcat.api.GCatConstants;
|
import org.gcube.gcat.api.GCatConstants;
|
||||||
|
import org.gcube.gcat.api.Role;
|
||||||
import org.gcube.gcat.oldutils.Validator;
|
import org.gcube.gcat.oldutils.Validator;
|
||||||
import org.gcube.gcat.profile.MetadataUtility;
|
import org.gcube.gcat.profile.MetadataUtility;
|
||||||
|
import org.gcube.gcat.social.PortalUser;
|
||||||
import org.gcube.gcat.social.SocialPost;
|
import org.gcube.gcat.social.SocialPost;
|
||||||
import org.gcube.gcat.utils.URIResolver;
|
import org.gcube.gcat.utils.URIResolver;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -55,6 +59,7 @@ public class CKANPackage extends CKAN {
|
||||||
// see https://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.dataset_purge
|
// see https://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.dataset_purge
|
||||||
public static final String ITEM_PURGE = CKAN.CKAN_API_PATH + "dataset_purge";
|
public static final String ITEM_PURGE = CKAN.CKAN_API_PATH + "dataset_purge";
|
||||||
|
|
||||||
|
|
||||||
// limit in https://docs.ckan.org/en/latest/api/index.html#ckan.logic.action.get.package_search
|
// limit in https://docs.ckan.org/en/latest/api/index.html#ckan.logic.action.get.package_search
|
||||||
protected static final String ROWS_KEY = "rows";
|
protected static final String ROWS_KEY = "rows";
|
||||||
// offset in https://docs.ckan.org/en/latest/api/index.html#ckan.logic.action.get.package_search
|
// offset in https://docs.ckan.org/en/latest/api/index.html#ckan.logic.action.get.package_search
|
||||||
|
@ -96,7 +101,10 @@ public class CKANPackage extends CKAN {
|
||||||
protected static final String SEARCHABLE_KEY = "searchable";
|
protected static final String SEARCHABLE_KEY = "searchable";
|
||||||
protected static final String CAPACITY_KEY = "capacity";
|
protected static final String CAPACITY_KEY = "capacity";
|
||||||
|
|
||||||
// protected static final String INCLUDE_PRIVATE_KEY = "include_private";
|
|
||||||
|
protected static final String CM_STATUS_QUERY_FILTER_KEY = "extras_systemcm_item_status";
|
||||||
|
|
||||||
|
protected static final String INCLUDE_PRIVATE_KEY = "include_private";
|
||||||
// protected static final String INCLUDE_DRAFTS_KEY = "include_drafts";
|
// protected static final String INCLUDE_DRAFTS_KEY = "include_drafts";
|
||||||
|
|
||||||
public static final String GROUPS_KEY = "groups";
|
public static final String GROUPS_KEY = "groups";
|
||||||
|
@ -338,9 +346,19 @@ public class CKANPackage extends CKAN {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ckanInstance.isModerationEnabled()) {
|
if(ckanInstance.isModerationEnabled()) {
|
||||||
// TODO
|
String q = parameters.get(GCatConstants.Q_KEY);
|
||||||
}
|
|
||||||
|
|
||||||
|
StringBuffer stringBuffer = new StringBuffer();
|
||||||
|
stringBuffer.append(CM_STATUS_QUERY_FILTER_KEY);
|
||||||
|
stringBuffer.append(":");
|
||||||
|
|
||||||
|
// Default se non viene richiesto esplicitamente lo status o per i ruoli che possono solo vedere approved
|
||||||
|
stringBuffer.append(CMItemStatus.APPROVED.getValue());
|
||||||
|
|
||||||
|
parameters.put(GCatConstants.Q_KEY, String.format("%s AND %s", q, stringBuffer.toString()));
|
||||||
|
|
||||||
|
parameters.put(INCLUDE_PRIVATE_KEY, String.valueOf(true));
|
||||||
|
}
|
||||||
|
|
||||||
return list(parameters);
|
return list(parameters);
|
||||||
}
|
}
|
||||||
|
@ -477,7 +495,7 @@ public class CKANPackage extends CKAN {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
extras = mapper.createArrayNode();
|
extras = ((ObjectNode) jsonNode).putArray(EXTRAS_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!found) {
|
if(!found) {
|
||||||
|
@ -528,17 +546,65 @@ public class CKANPackage extends CKAN {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected CMItemStatus getCMItemStatus() {
|
||||||
|
|
||||||
|
String cmItemStatusString = CMItemStatus.APPROVED.getValue();
|
||||||
|
boolean found = false;
|
||||||
|
if(result.has(EXTRAS_KEY)) {
|
||||||
|
ArrayNode extras = (ArrayNode) result.get(EXTRAS_KEY);
|
||||||
|
for(JsonNode extra : extras) {
|
||||||
|
if(extra.has(EXTRAS_KEY_KEY) && extra.get(EXTRAS_KEY_KEY).asText().compareTo(GCatConstants.CM_ITEM_STATUS) == 0) {
|
||||||
|
cmItemStatusString = extra.get(EXTRAS_VALUE_KEY).asText();
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 updateds
|
||||||
|
return cmItemStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmItemStatus;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String read() {
|
public String read() {
|
||||||
try {
|
try {
|
||||||
if(ckanInstance.isModerationEnabled()) {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
String ret = super.read();
|
String ret = super.read();
|
||||||
result = mapper.readTree(ret);
|
result = mapper.readTree(ret);
|
||||||
result = cleanResult(result);
|
result = cleanResult(result);
|
||||||
|
|
||||||
|
if(ckanInstance.isModerationEnabled()) {
|
||||||
|
|
||||||
|
CMItemStatus cmItemStatus = getCMItemStatus();
|
||||||
|
|
||||||
|
if(cmItemStatus == CMItemStatus.APPROVED) {
|
||||||
|
return getAsString(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
PortalUser portalUser = ckanUser.getPortalUser();
|
||||||
|
|
||||||
|
if(result.get(AUTHOR_EMAIL_KEY).asText().compareTo(portalUser.getEMail())==0) {
|
||||||
|
// The author is entitled to read its own items independently from the status
|
||||||
|
return getAsString(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ckanUser.getRole() == Role.ADMIN || portalUser.isCatalogueModerator()) {
|
||||||
|
// Catalogue-Admin and Catalogue-Moderator are entitled to read items with any statues
|
||||||
|
return getAsString(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ForbiddenException("You are not entitled to read a " + cmItemStatus.getValue() + " item");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return getAsString(result);
|
return getAsString(result);
|
||||||
|
|
||||||
} catch(WebApplicationException e) {
|
} catch(WebApplicationException e) {
|
||||||
throw e;
|
throw e;
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
|
@ -555,11 +621,17 @@ public class CKANPackage extends CKAN {
|
||||||
|
|
||||||
if(ckanInstance.isModerationEnabled()) {
|
if(ckanInstance.isModerationEnabled()) {
|
||||||
// TODO
|
// TODO
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
JsonNode jsonNode = validateJson(json);
|
JsonNode jsonNode = validateJson(json);
|
||||||
|
|
||||||
|
if(ckanInstance.isModerationEnabled()) {
|
||||||
|
addExtraField(jsonNode, GCatConstants.CM_ITEM_STATUS, CMItemStatus.APPROVED.getValue());
|
||||||
|
addExtraField(jsonNode, GCatConstants.CM_ITEM_VISIBILITY, CMItemVisibility.PUBLIC.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ArrayNode resourcesToBeCreated = mapper.createArrayNode();
|
ArrayNode resourcesToBeCreated = mapper.createArrayNode();
|
||||||
if(jsonNode.has(RESOURCES_KEY)) {
|
if(jsonNode.has(RESOURCES_KEY)) {
|
||||||
resourcesToBeCreated = (ArrayNode) jsonNode.get(RESOURCES_KEY);
|
resourcesToBeCreated = (ArrayNode) jsonNode.get(RESOURCES_KEY);
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
package org.gcube.gcat.persistence.ckan;
|
package org.gcube.gcat.persistence.ckan;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.ws.rs.InternalServerErrorException;
|
import javax.ws.rs.InternalServerErrorException;
|
||||||
import javax.ws.rs.WebApplicationException;
|
import javax.ws.rs.WebApplicationException;
|
||||||
import javax.ws.rs.core.Response.Status;
|
import javax.ws.rs.core.Response.Status;
|
||||||
|
|
||||||
|
import org.gcube.gcat.api.Role;
|
||||||
import org.gcube.gcat.social.PortalUser;
|
import org.gcube.gcat.social.PortalUser;
|
||||||
import org.gcube.gcat.utils.ContextUtility;
|
import org.gcube.gcat.utils.ContextUtility;
|
||||||
import org.gcube.gcat.utils.RandomString;
|
import org.gcube.gcat.utils.RandomString;
|
||||||
|
@ -46,60 +45,6 @@ public class CKANUser extends CKAN {
|
||||||
|
|
||||||
private static final String API_KEY = "apikey";
|
private static final String API_KEY = "apikey";
|
||||||
|
|
||||||
public enum Role {
|
|
||||||
MEMBER("Catalogue-Member", "member"), EDITOR("Catalogue-Editor", "editor"), ADMIN("Catalogue-Admin", "admin");
|
|
||||||
|
|
||||||
private final String portalRole;
|
|
||||||
private final String ckanRole;
|
|
||||||
|
|
||||||
Role(String portalRole, String ckanRole) {
|
|
||||||
this.portalRole = portalRole;
|
|
||||||
this.ckanRole = ckanRole;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPortalRole() {
|
|
||||||
return portalRole;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCkanRole() {
|
|
||||||
return ckanRole;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static final Map<String,Role> ROLE_BY_PORTAL_ROLE;
|
|
||||||
protected static final Map<String,Role> ROLE_BY_CKAN_ROLE;
|
|
||||||
|
|
||||||
static {
|
|
||||||
ROLE_BY_PORTAL_ROLE = new HashMap<String,Role>();
|
|
||||||
|
|
||||||
// null or empty string identify a member
|
|
||||||
ROLE_BY_PORTAL_ROLE.put(null, MEMBER);
|
|
||||||
ROLE_BY_PORTAL_ROLE.put("", MEMBER);
|
|
||||||
|
|
||||||
ROLE_BY_CKAN_ROLE = new HashMap<String,Role>();
|
|
||||||
|
|
||||||
for(Role role : Role.values()) {
|
|
||||||
ROLE_BY_PORTAL_ROLE.put(role.getPortalRole(), role);
|
|
||||||
ROLE_BY_CKAN_ROLE.put(role.getCkanRole(), role);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Role getRoleFromPortalRole(String portalRole) {
|
|
||||||
return ROLE_BY_PORTAL_ROLE.get(portalRole);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getCkanRoleFromPortalRole(String portalRole) {
|
|
||||||
return getRoleFromPortalRole(portalRole).getCkanRole();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Role getRoleFromCkanRole(String ckanRole) {
|
|
||||||
return ROLE_BY_CKAN_ROLE.get(ckanRole);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getPortalRoleFromCkanRole(String ckanRole) {
|
|
||||||
return getRoleFromCkanRole(ckanRole).getPortalRole();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected PortalUser portalUser;
|
protected PortalUser portalUser;
|
||||||
protected Role role;
|
protected Role role;
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,8 @@ import org.gcube.common.resources.gcore.GenericResource;
|
||||||
import org.gcube.common.resources.gcore.Resources;
|
import org.gcube.common.resources.gcore.Resources;
|
||||||
import org.gcube.datacatalogue.metadatadiscovery.reader.MetadataFormatDiscovery;
|
import org.gcube.datacatalogue.metadatadiscovery.reader.MetadataFormatDiscovery;
|
||||||
import org.gcube.datacatalogue.metadatadiscovery.reader.QueryForResourceUtil;
|
import org.gcube.datacatalogue.metadatadiscovery.reader.QueryForResourceUtil;
|
||||||
|
import org.gcube.gcat.api.Role;
|
||||||
import org.gcube.gcat.persistence.ckan.CKANUser;
|
import org.gcube.gcat.persistence.ckan.CKANUser;
|
||||||
import org.gcube.gcat.persistence.ckan.CKANUser.Role;
|
|
||||||
import org.gcube.gcat.persistence.ckan.CKANUserCache;
|
import org.gcube.gcat.persistence.ckan.CKANUserCache;
|
||||||
import org.gcube.gcat.utils.Constants;
|
import org.gcube.gcat.utils.Constants;
|
||||||
import org.gcube.informationsystem.publisher.RegistryPublisher;
|
import org.gcube.informationsystem.publisher.RegistryPublisher;
|
||||||
|
|
|
@ -19,8 +19,8 @@ import org.gcube.common.resources.gcore.GenericResource;
|
||||||
import org.gcube.common.resources.gcore.Resources;
|
import org.gcube.common.resources.gcore.Resources;
|
||||||
import org.gcube.datacatalogue.metadatadiscovery.reader.MetadataFormatDiscovery;
|
import org.gcube.datacatalogue.metadatadiscovery.reader.MetadataFormatDiscovery;
|
||||||
import org.gcube.datacatalogue.metadatadiscovery.reader.QueryForResourceUtil;
|
import org.gcube.datacatalogue.metadatadiscovery.reader.QueryForResourceUtil;
|
||||||
|
import org.gcube.gcat.api.Role;
|
||||||
import org.gcube.gcat.persistence.ckan.CKANUser;
|
import org.gcube.gcat.persistence.ckan.CKANUser;
|
||||||
import org.gcube.gcat.persistence.ckan.CKANUser.Role;
|
|
||||||
import org.gcube.gcat.persistence.ckan.CKANUserCache;
|
import org.gcube.gcat.persistence.ckan.CKANUserCache;
|
||||||
import org.gcube.gcat.utils.Constants;
|
import org.gcube.gcat.utils.Constants;
|
||||||
import org.gcube.informationsystem.publisher.RegistryPublisher;
|
import org.gcube.informationsystem.publisher.RegistryPublisher;
|
||||||
|
|
|
@ -8,12 +8,16 @@ import java.util.List;
|
||||||
import javax.ws.rs.InternalServerErrorException;
|
import javax.ws.rs.InternalServerErrorException;
|
||||||
|
|
||||||
import org.gcube.common.gxhttp.request.GXHTTPStringRequest;
|
import org.gcube.common.gxhttp.request.GXHTTPStringRequest;
|
||||||
|
import org.gcube.gcat.api.GCatConstants;
|
||||||
import org.gcube.gcat.utils.HTTPUtility;
|
import org.gcube.gcat.utils.HTTPUtility;
|
||||||
|
|
||||||
import org.gcube.com.fasterxml.jackson.databind.JsonNode;
|
import org.gcube.com.fasterxml.jackson.databind.JsonNode;
|
||||||
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
|
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.ArrayNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
public class PortalUser {
|
public class PortalUser {
|
||||||
|
|
||||||
protected static final String RESPONSE_SUCCESS_KEY = "success";
|
protected static final String RESPONSE_SUCCESS_KEY = "success";
|
||||||
|
@ -42,6 +46,8 @@ public class PortalUser {
|
||||||
|
|
||||||
protected List<String> roles;
|
protected List<String> roles;
|
||||||
|
|
||||||
|
protected Boolean catalogueModerator;
|
||||||
|
|
||||||
public PortalUser() {
|
public PortalUser() {
|
||||||
this.objectMapper = new ObjectMapper();
|
this.objectMapper = new ObjectMapper();
|
||||||
}
|
}
|
||||||
|
@ -120,6 +126,14 @@ public class PortalUser {
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isCatalogueModerator() {
|
||||||
|
if(catalogueModerator == null) {
|
||||||
|
catalogueModerator = getRoles().contains(GCatConstants.CATALOGUE_MODERATOR);
|
||||||
|
}
|
||||||
|
return catalogueModerator;
|
||||||
|
}
|
||||||
|
|
||||||
public String getJobTitle() {
|
public String getJobTitle() {
|
||||||
if(jobTitle == null) {
|
if(jobTitle == null) {
|
||||||
jobTitle = getOAuthUserProfile().get(OAUTH_USER_PROFILE_JOB_TITLE_KEY).asText();
|
jobTitle = getOAuthUserProfile().get(OAUTH_USER_PROFILE_JOB_TITLE_KEY).asText();
|
||||||
|
|
|
@ -54,6 +54,7 @@ public class CKANPackageTest extends ContextTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void list() throws Exception {
|
public void list() throws Exception {
|
||||||
|
ContextTest.setContextByName("/gcube/devsec/devVRE");
|
||||||
CKANPackage ckanPackage = new CKANPackage();
|
CKANPackage ckanPackage = new CKANPackage();
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
String ret = ckanPackage.list(10, 0);
|
String ret = ckanPackage.list(10, 0);
|
||||||
|
@ -242,7 +243,8 @@ public class CKANPackageTest extends ContextTest {
|
||||||
* Workspace(luca.frosini) > RESTful Transaction Model v 1.0.pdf
|
* Workspace(luca.frosini) > RESTful Transaction Model v 1.0.pdf
|
||||||
* https://data1-d.d4science.org/shub/E_aThRa1NpWFJpTGEydEU2bEJhMXNjZy8wK3BxekJKYnpYTy81cUkwZVdicEZ0aGFRZmY4MkRnUC8xWW0zYzVoVg==
|
* https://data1-d.d4science.org/shub/E_aThRa1NpWFJpTGEydEU2bEJhMXNjZy8wK3BxekJKYnpYTy81cUkwZVdicEZ0aGFRZmY4MkRnUC8xWW0zYzVoVg==
|
||||||
* https://goo.gl/J8AwQW
|
* https://goo.gl/J8AwQW
|
||||||
*
|
* ContextTest.setContextByName("/gcube/devsec/devVRE");
|
||||||
|
|
||||||
*
|
*
|
||||||
* Workspace(luca.frosini) > RESTful Transaction Model v 1.1.pdf
|
* Workspace(luca.frosini) > RESTful Transaction Model v 1.1.pdf
|
||||||
* https://data1-d.d4science.org/shub/E_NkhrbVV4VTluT0RKVUtCRldobFZTQU5ySTZneFdpUzJ2UjJBNlZWNDlURDVHamo4WjY5RnlrcHZGTGNkT2prUg==
|
* https://data1-d.d4science.org/shub/E_NkhrbVV4VTluT0RKVUtCRldobFZTQU5ySTZneFdpUzJ2UjJBNlZWNDlURDVHamo4WjY5RnlrcHZGTGNkT2prUg==
|
||||||
|
@ -330,7 +332,6 @@ public class CKANPackageTest extends ContextTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void create() throws Exception {
|
public void create() throws Exception {
|
||||||
ContextTest.setContextByName("/gcube/devsec/devVRE");
|
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
createPackage(mapper);
|
createPackage(mapper);
|
||||||
}
|
}
|
||||||
|
@ -346,8 +347,6 @@ public class CKANPackageTest extends ContextTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createReadUpdateUpdatePurge() throws Exception {
|
public void createReadUpdateUpdatePurge() throws Exception {
|
||||||
ContextTest.setContextByName("/gcube/devsec/devVRE");
|
|
||||||
|
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
createPackage(mapper);
|
createPackage(mapper);
|
||||||
|
|
||||||
|
@ -420,7 +419,6 @@ public class CKANPackageTest extends ContextTest {
|
||||||
@Test
|
@Test
|
||||||
//(expected = NotFoundException.class)
|
//(expected = NotFoundException.class)
|
||||||
public void delete() throws Exception {
|
public void delete() throws Exception {
|
||||||
ContextTest.setContextByName("/gcube/devNext/NextNext");
|
|
||||||
CKANPackage ckanPackage = new CKANPackage();
|
CKANPackage ckanPackage = new CKANPackage();
|
||||||
ckanPackage.setName(ITEM_NAME_VALUE);
|
ckanPackage.setName(ITEM_NAME_VALUE);
|
||||||
ckanPackage.delete(true);
|
ckanPackage.delete(true);
|
||||||
|
|
Loading…
Reference in New Issue