501 lines
18 KiB
Java
501 lines
18 KiB
Java
package org.gcube.portlets.widgets.ckancontentmoderator.server;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
|
|
import org.gcube.common.scope.api.ScopeProvider;
|
|
import org.gcube.datacatalogue.utillibrary.gcat.GCatCaller;
|
|
import org.gcube.datacatalogue.utillibrary.server.DataCatalogueImpl;
|
|
import org.gcube.datacatalogue.utillibrary.server.cms.CatalogueContentModeratorSystem;
|
|
import org.gcube.datacatalogue.utillibrary.shared.ItemStatus;
|
|
import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanDataset;
|
|
import org.gcube.portlets.widgets.ckancontentmoderator.client.CkanContentModeratorService;
|
|
import org.gcube.portlets.widgets.ckancontentmoderator.client.ContentModeratorWidgetConstants;
|
|
import org.gcube.portlets.widgets.ckancontentmoderator.server.CkanContentModeratorUtil.QUERY_OPERATOR;
|
|
import org.gcube.portlets.widgets.ckancontentmoderator.shared.CMSUserRole;
|
|
import org.gcube.portlets.widgets.ckancontentmoderator.shared.CatalogueDataset;
|
|
import org.gcube.portlets.widgets.ckancontentmoderator.shared.ModerationUserRole;
|
|
import org.gcube.portlets.widgets.ckancontentmoderator.shared.OperationReport;
|
|
import org.gcube.portlets.widgets.ckancontentmoderator.shared.SearchedData;
|
|
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
|
|
|
|
/**
|
|
* The Class CkanContentModeratorServiceImpl.
|
|
*
|
|
* @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it
|
|
*
|
|
* Jan 11, 2022
|
|
* @return the boolean
|
|
*/
|
|
@SuppressWarnings("serial")
|
|
public class CkanContentModeratorServiceImpl extends RemoteServiceServlet implements CkanContentModeratorService {
|
|
|
|
private static Logger LOG = LoggerFactory.getLogger(CkanContentModeratorServiceImpl.class);
|
|
|
|
/**
|
|
* Checks if is moderation enabled.
|
|
*
|
|
* @param reloadConfig the reload config
|
|
* @return the boolean
|
|
*/
|
|
@Override
|
|
public Boolean isModerationEnabled(boolean reloadConfig) {
|
|
LOG.info("called isContentModeratorEnabled");
|
|
String scope = setContexts();
|
|
boolean isModerationEnabled = false;
|
|
try {
|
|
DataCatalogueImpl catalogueImpl = CatalogueCMSFactory.getFactory().getCatalogueImplPerScope(scope);
|
|
CatalogueContentModeratorSystem cmsInstance = catalogueImpl.getCatalogueContentModerator();
|
|
isModerationEnabled = cmsInstance.isModerationEnabled(reloadConfig);
|
|
} catch (Exception e) {
|
|
LOG.error("Error occured on checking isContentModeratorEnabled, so returning false", e);
|
|
return false;
|
|
}
|
|
return isModerationEnabled;
|
|
}
|
|
|
|
/**
|
|
* Checks if is moderator role is assigned to working user in the context.
|
|
*
|
|
* @return the moderation user role
|
|
* @throws Exception the exception
|
|
*/
|
|
@Override
|
|
public Boolean isModeratorRoleAssigned() throws Exception {
|
|
LOG.info("called isModeratorRoleAssigned");
|
|
ModerationUserRole userRole = getCMSRolesForUserInTheContext();
|
|
|
|
boolean isCatalogueModerator = false;
|
|
if (userRole != null && userRole.getRoles() != null
|
|
&& userRole.getRoles().contains(CMSUserRole.CATALOGUE_MODERATOR)) {
|
|
LOG.info("called isModeratorRoleAssigned");
|
|
isCatalogueModerator = true;
|
|
}
|
|
LOG.info("is " + CMSUserRole.CATALOGUE_MODERATOR.getRoleName() + " assigned? " + isCatalogueModerator);
|
|
return isCatalogueModerator;
|
|
}
|
|
|
|
/**
|
|
* Exists my item in moderation.
|
|
*
|
|
* @return true if the user has at least one item moderatorated or in
|
|
* moderation.
|
|
* @throws Exception the exception
|
|
*/
|
|
@Override
|
|
public Boolean existsMyItemInModeration() throws Exception {
|
|
LOG.info("called existsMyItemInModeration");
|
|
try {
|
|
|
|
/*
|
|
* if(!GcubeContextUtil.isWithinPortal()) {
|
|
* LOG.warn("#### DEV MODE ENABLED #######"); boolean defaultValue = true;
|
|
* LOG.info("DEV MODE: existsMyItemInModeration returning: " + defaultValue);
|
|
* return defaultValue; }
|
|
*/
|
|
|
|
String scope = setContexts();
|
|
DataCatalogueImpl catalogueImpl = CatalogueCMSFactory.getFactory().getCatalogueImplPerScope(scope);
|
|
|
|
GCubeUser user = GcubeContextUtil.getCurrentUser(getThreadLocalRequest());
|
|
String valueOfQueryEmails = CkanContentModeratorUtil.userSOLRQueryForEmails(user, QUERY_OPERATOR.OR);
|
|
|
|
StringBuilder emailsValuesBuilder = new StringBuilder();
|
|
// QUERYING AUTHOR_MAIL. IT MUST BE IN LIST OF EMAILs
|
|
emailsValuesBuilder
|
|
.append(ContentModeratorWidgetConstants.CKAN_FIELD_NAME_AUTHOR_MAIL + ":" + valueOfQueryEmails);
|
|
|
|
Map<String, String> params = new HashMap<String, String>(1);
|
|
params.put("q", emailsValuesBuilder.toString());
|
|
// QUERYING THE ITEM HAVING ANY MODERATIONS STATUS
|
|
params.put(GCatCaller.MODERATOR_ITEM_STATUS_PARAMETER, GCatCaller.MODERATOR_ITEM_ANY_STATUS_VALUE);
|
|
|
|
List<String> listItems = catalogueImpl.performQueryForItems(params);
|
|
LOG.debug("existsMyItemInModeration query returned items: " + listItems);
|
|
|
|
boolean haveItemInModeration = false;
|
|
|
|
if (listItems != null && listItems.size() > 0) {
|
|
haveItemInModeration = true;
|
|
}
|
|
|
|
LOG.info("existsMyItemInModeration returning: " + haveItemInModeration);
|
|
return haveItemInModeration;
|
|
|
|
} catch (Exception e) {
|
|
LOG.warn("Error occurred on checking existsMyItemInModeration, so returning false");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the CMS roles for user in the context.
|
|
*
|
|
* @return the CMS roles for user in the context
|
|
* @throws Exception the exception
|
|
*/
|
|
@Override
|
|
public ModerationUserRole getCMSRolesForUserInTheContext() throws Exception {
|
|
LOG.info("called getCMSRolesForUserInTheContext");
|
|
setContexts();
|
|
List<CMSUserRole> roles = GcubeContextUtil.getCMSRoleForUserInTheScope(getThreadLocalRequest());
|
|
|
|
GcubeContextUtil.getCurrentUser(getThreadLocalRequest());
|
|
ModerationUserRole userRole = new ModerationUserRole(getServletInfo(), roles);
|
|
LOG.info("return: " + userRole);
|
|
return userRole;
|
|
}
|
|
|
|
/**
|
|
* Sets the contexts.
|
|
*
|
|
* @return the scope operating in
|
|
*/
|
|
private String setContexts() {
|
|
String scope = GcubeContextUtil.getCurrentScope(this.getThreadLocalRequest());
|
|
ScopeProvider.instance.set(scope);
|
|
|
|
GCubeUser user = GcubeContextUtil.getCurrentUser(this.getThreadLocalRequest());
|
|
if (user != null) {
|
|
String token = GcubeContextUtil.getCurrentToken(scope, user.getUsername());
|
|
SecurityTokenProvider.instance.set(token);
|
|
}
|
|
return scope;
|
|
}
|
|
|
|
/**
|
|
* Gets the list items for status.
|
|
*
|
|
* @param theStatus the the status
|
|
* @param offset the offset
|
|
* @param limit the limit
|
|
* @param restrictedToLoggedInUser if true restricts the list of items to logged
|
|
* in user
|
|
* @param sortForField the sort for field
|
|
* @return the list items for status
|
|
* @throws Exception the exception
|
|
*/
|
|
@Override
|
|
public List<CatalogueDataset> getListItemsForStatus(ItemStatus theStatus, int offset, int limit,
|
|
boolean restrictedToLoggedInUser, String sortForField) throws Exception {
|
|
LOG.info("called getListItemsForStatus with [status: " + theStatus + ", offset: " + offset + ", limit: " + limit
|
|
+ ", restrictedToLoggedInUser: " + restrictedToLoggedInUser + "]");
|
|
List<CatalogueDataset> datasetList = null;
|
|
try {
|
|
String scope = setContexts();
|
|
DataCatalogueImpl catalogueImpl = CatalogueCMSFactory.getFactory().getCatalogueImplPerScope(scope);
|
|
CatalogueContentModeratorSystem cmsInstance = catalogueImpl.getCatalogueContentModerator();
|
|
|
|
Map<String, String> filters = null;
|
|
if (restrictedToLoggedInUser) {
|
|
filters = new HashMap<String, String>(1);
|
|
GCubeUser user = GcubeContextUtil.getCurrentUser(getThreadLocalRequest());
|
|
String valueOfQueryEmails = CkanContentModeratorUtil.userSOLRQueryForEmails(user, QUERY_OPERATOR.OR);
|
|
filters.put(ContentModeratorWidgetConstants.CKAN_FIELD_NAME_AUTHOR_MAIL, valueOfQueryEmails);
|
|
}
|
|
|
|
List<CkanDataset> datasets = cmsInstance.getListItemsForStatus(theStatus, limit, offset, filters,
|
|
sortForField);
|
|
if (datasets != null) {
|
|
int size = datasets.size();
|
|
datasetList = new ArrayList<CatalogueDataset>(size);
|
|
LOG.info("datasetList for input parameters returned by CMS has size: " + size);
|
|
for (CkanDataset ckanDataset : datasets) {
|
|
CatalogueDataset ds = toPatchedCatalogueDataset(ckanDataset, catalogueImpl.getCatalogueUrl());
|
|
LOG.trace("converted dataset is: " + ds);
|
|
datasetList.add(ds);
|
|
}
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
LOG.error("Error occurred on reading items for status: " + theStatus, e);
|
|
throw e;
|
|
}
|
|
|
|
LOG.info("returning " + datasetList.size() + " dataset");
|
|
return datasetList;
|
|
}
|
|
|
|
private CatalogueDataset toPatchedCatalogueDataset(CkanDataset ckanDataset, String catalogueURL) {
|
|
if (ckanDataset == null)
|
|
return null;
|
|
|
|
CatalogueDataset ds = CatalogueBeansConverter.toCatalogueDataset.apply(ckanDataset);
|
|
String datasetURL = String.format("%s/dataset/%s", catalogueURL, ds.getName());
|
|
ds.setUrl(datasetURL);
|
|
return ds;
|
|
}
|
|
|
|
/**
|
|
* Gets the item for name.
|
|
*
|
|
* @param itemName the item name
|
|
* @return the item for name
|
|
* @throws Exception the exception
|
|
*/
|
|
@Override
|
|
public CatalogueDataset getItemForName(String itemName) throws Exception {
|
|
LOG.info("called getItemForName for: " + itemName);
|
|
CatalogueDataset ds = null;
|
|
try {
|
|
String scope = setContexts();
|
|
DataCatalogueImpl catalogueImpl = CatalogueCMSFactory.getFactory().getCatalogueImplPerScope(scope);
|
|
GCubeUser user = GcubeContextUtil.getCurrentUser(this.getThreadLocalRequest());
|
|
|
|
boolean moderationCheckPassed = false;
|
|
|
|
if (user != null) {
|
|
CkanDataset ckanDataset = catalogueImpl.getDataset(itemName, user.getUsername());
|
|
ds = null;
|
|
if (ckanDataset != null) {
|
|
ds = toPatchedCatalogueDataset(ckanDataset, catalogueImpl.getCatalogueUrl());
|
|
|
|
Boolean userModerator = isModeratorRoleAssigned();
|
|
moderationCheckPassed = userModerator?true:false;
|
|
LOG.info("Moderation check: is the user a Moderator? "+moderationCheckPassed);
|
|
//The user is not a Moderator, yes otherwise
|
|
if(!moderationCheckPassed) {
|
|
String datasetAuthorMail = ds.getAuthorEmail();
|
|
String userMail = user.getEmail();
|
|
if(datasetAuthorMail!=null && userMail!=null && datasetAuthorMail.compareTo(userMail)==0) {
|
|
//The user is the owner of the dataset, so he/she can view the dataset (moderation check passed)
|
|
moderationCheckPassed = true;
|
|
}
|
|
LOG.info("Moderation check: is the user the owner of the dataset? "+moderationCheckPassed);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!moderationCheckPassed) {
|
|
LOG.info("Moderation ckeck not passed, returning null");
|
|
ds = null;
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
LOG.error("Error occurred on reading item for name: " + itemName, e);
|
|
throw e;
|
|
}
|
|
|
|
LOG.info("getItemForName "+itemName+", returning: " + ds);
|
|
return ds;
|
|
}
|
|
|
|
/**
|
|
* Sets the status.
|
|
*
|
|
* @param theStatus the the status
|
|
* @param itemNames the item names
|
|
* @return the operation report
|
|
* @throws Exception the exception
|
|
*/
|
|
@Override
|
|
public OperationReport setStatus(ItemStatus theStatus, List<String> itemNames) throws Exception {
|
|
LOG.info("Called set status " + theStatus + " for Items with name: " + itemNames);
|
|
|
|
try {
|
|
String scope = setContexts();
|
|
DataCatalogueImpl catalogueImpl = CatalogueCMSFactory.getFactory().getCatalogueImplPerScope(scope);
|
|
Map<String, String> errorMapItems = new HashMap<String, String>();
|
|
List<String> changedStatusListItems = new ArrayList<String>();
|
|
for (String itemName : itemNames) {
|
|
try {
|
|
catalogueImpl.refreshDataset(itemName);
|
|
changedStatusListItems.add(itemName);
|
|
} catch (Exception e) {
|
|
LOG.warn("Error when setting status (updating) the itemName: " + itemName, e);
|
|
errorMapItems.put(itemName, e.getMessage());
|
|
}
|
|
}
|
|
|
|
return new OperationReport(theStatus.getLabel(), changedStatusListItems, errorMapItems);
|
|
|
|
} catch (Exception e) {
|
|
LOG.error(e.getMessage(), e);
|
|
throw new Exception("Error occurred on updating the status for item/s: " + itemNames + ". Caused by: "
|
|
+ e.getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Approve item.
|
|
*
|
|
* @param itemNames the item names
|
|
* @param moderatorMessage the moderator message
|
|
* @return the operation report
|
|
* @throws Exception the exception
|
|
*/
|
|
@Override
|
|
public OperationReport approveItem(List<String> itemNames, String moderatorMessage) throws Exception {
|
|
LOG.info("Called approveItem with name/s: " + itemNames);
|
|
|
|
try {
|
|
String scope = setContexts();
|
|
DataCatalogueImpl catalogueImpl = CatalogueCMSFactory.getFactory().getCatalogueImplPerScope(scope);
|
|
CatalogueContentModeratorSystem cmsInstance = catalogueImpl.getCatalogueContentModerator();
|
|
|
|
Map<String, String> errorMapItems = new HashMap<String, String>();
|
|
List<String> approvedListItems = new ArrayList<String>();
|
|
for (String itemName : itemNames) {
|
|
try {
|
|
cmsInstance.approveItem(itemName, moderatorMessage);
|
|
approvedListItems.add(itemName);
|
|
} catch (Exception e) {
|
|
LOG.warn("Error when approving itemName: " + itemName, e);
|
|
errorMapItems.put(itemName, e.getMessage());
|
|
}
|
|
}
|
|
|
|
return new OperationReport(ItemStatus.APPROVED.getLabel(), approvedListItems, errorMapItems);
|
|
|
|
} catch (Exception e) {
|
|
LOG.error(e.getMessage(), e);
|
|
throw new Exception("Error occurred on approving item/s: " + itemNames + ". Caused by: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reject item.
|
|
*
|
|
* @param itemNames the item names
|
|
* @param permanentlyDelete the permanently delete
|
|
* @param reasonMsg the reason msg
|
|
* @return the operation report
|
|
* @throws Exception the exception
|
|
*/
|
|
@Override
|
|
public OperationReport rejectItem(List<String> itemNames, boolean permanentlyDelete, String reasonMsg)
|
|
throws Exception {
|
|
LOG.info("Called rejectItem with name/s: " + itemNames + ", permanentlyDelete: " + permanentlyDelete);
|
|
|
|
try {
|
|
String scope = setContexts();
|
|
DataCatalogueImpl catalogueImpl = CatalogueCMSFactory.getFactory().getCatalogueImplPerScope(scope);
|
|
CatalogueContentModeratorSystem cmsInstance = catalogueImpl.getCatalogueContentModerator();
|
|
|
|
Map<String, String> errorMapItems = new HashMap<String, String>();
|
|
List<String> passedListItems = new ArrayList<String>();
|
|
for (String itemName : itemNames) {
|
|
try {
|
|
cmsInstance.rejectItem(itemName, permanentlyDelete, reasonMsg);
|
|
passedListItems.add(itemName);
|
|
} catch (Exception e) {
|
|
LOG.warn("Error when rejecting itemName: " + itemName, e);
|
|
errorMapItems.put(itemName, e.getMessage());
|
|
}
|
|
}
|
|
|
|
return new OperationReport(ItemStatus.REJECTED.getLabel(), passedListItems, errorMapItems);
|
|
|
|
} catch (Exception e) {
|
|
LOG.error(e.getMessage(), e);
|
|
throw new Exception("Error occurred on rejecting item/s: " + itemNames + ". Caused by: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Permanently delete.
|
|
*
|
|
* @param itemNames the item names
|
|
* @return the operation report
|
|
* @throws Exception the exception
|
|
*/
|
|
@Override
|
|
public OperationReport permanentlyDelete(List<String> itemNames) throws Exception {
|
|
LOG.info("Called permanently delete Items with name/s: " + itemNames);
|
|
|
|
try {
|
|
String scope = setContexts();
|
|
DataCatalogueImpl catalogueImpl = CatalogueCMSFactory.getFactory().getCatalogueImplPerScope(scope);
|
|
CatalogueContentModeratorSystem cmsInstance = catalogueImpl.getCatalogueContentModerator();
|
|
|
|
Map<String, String> errorMapItems = new HashMap<String, String>();
|
|
List<String> passedListItems = new ArrayList<String>();
|
|
for (String itemName : itemNames) {
|
|
try {
|
|
cmsInstance.permanentlyDelete(itemName);
|
|
passedListItems.add(itemName);
|
|
} catch (Exception e) {
|
|
LOG.warn("Error when deleting permanently the itemName: " + itemName, e);
|
|
errorMapItems.put(itemName, e.getMessage());
|
|
}
|
|
}
|
|
|
|
return new OperationReport("Permanently Delete", passedListItems, errorMapItems);
|
|
|
|
} catch (Exception e) {
|
|
LOG.error(e.getMessage(), e);
|
|
throw new Exception(
|
|
"Error occurred on permanently delete item/s: " + itemNames + ". Caused by: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the data for status.
|
|
*
|
|
* @param status the status
|
|
* @param offset the offset
|
|
* @param limit the limit
|
|
* @param serverStartIndex the server start index
|
|
* @param restrictedToLoggedInUser the restricted to logged in user
|
|
* @param sortForField the sort for field
|
|
* @return the data for status
|
|
* @throws Exception the exception
|
|
*/
|
|
@Override
|
|
public SearchedData getDataForStatus(ItemStatus status, int offset, int limit, int serverStartIndex,
|
|
boolean restrictedToLoggedInUser, String sortForField) throws Exception {
|
|
LOG.info("called getDataForStatus [status: " + status + ", offset: " + offset + ", limit: " + limit
|
|
+ ", serverIndex: " + serverStartIndex);
|
|
|
|
String scope = setContexts();
|
|
int searchStartIndex = offset;
|
|
CatalogueContentModeratorSystem cmsInstance = CatalogueCMSFactory.getFactory().getCMSPerScope(scope);
|
|
SearchedData searchedData = new SearchedData(offset, limit, searchStartIndex, false);
|
|
|
|
Map<String, String> filters = null;
|
|
if (restrictedToLoggedInUser) {
|
|
filters = new HashMap<String, String>(1);
|
|
GCubeUser user = GcubeContextUtil.getCurrentUser(getThreadLocalRequest());
|
|
String valueOfQueryEmails = CkanContentModeratorUtil.userSOLRQueryForEmails(user, QUERY_OPERATOR.OR);
|
|
filters.put(ContentModeratorWidgetConstants.CKAN_FIELD_NAME_AUTHOR_MAIL, valueOfQueryEmails);
|
|
}
|
|
|
|
long totalItemsForStatus = cmsInstance.countListItemsForStatus(status, filters);
|
|
LOG.info("totalItemsForStatus " + status + " are : " + totalItemsForStatus);
|
|
List<CatalogueDataset> listDataset = new ArrayList<CatalogueDataset>();
|
|
try {
|
|
LOG.debug("getListItemsForStatus with searchStartIndex: " + searchStartIndex + ", limit: " + limit);
|
|
listDataset = getListItemsForStatus(status, searchStartIndex, limit, restrictedToLoggedInUser,
|
|
sortForField);
|
|
} catch (Exception e) {
|
|
String error = "Error occurred on getting items for status: " + status;
|
|
LOG.error(error, e);
|
|
throw new Exception(error + ". Cause: " + e.getMessage());
|
|
}
|
|
|
|
int listDatasetSize = listDataset.size();
|
|
LOG.debug("Returned " + listDatasetSize + " with above parameters");
|
|
searchedData.setData(listDataset);
|
|
searchedData.setTotalItems(totalItemsForStatus);
|
|
|
|
if (listDatasetSize == limit || listDatasetSize == 0) {
|
|
LOG.debug("Page completed returning " + listDatasetSize + " items");
|
|
int newOffset = searchStartIndex + offset;
|
|
searchedData.setServerSearchFinished(newOffset > totalItemsForStatus || listDatasetSize == 0);
|
|
LOG.debug("is Search finished: " + searchedData.isServerSearchFinished());
|
|
return searchedData;
|
|
}
|
|
|
|
LOG.debug("Returning: " + searchedData);
|
|
return searchedData;
|
|
}
|
|
|
|
}
|