diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index 9bafa34..83309d3 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -1,5 +1,6 @@ - + + @@ -80,7 +81,8 @@ - + + @@ -161,7 +163,8 @@ - + + @@ -242,7 +245,8 @@ - + + @@ -323,7 +327,8 @@ - + + @@ -356,10 +361,11 @@ - + uses - + + @@ -440,7 +446,8 @@ - + + @@ -521,7 +528,8 @@ - + + @@ -602,7 +610,8 @@ - + + diff --git a/CHANGELOG.md b/CHANGELOG.md index 40fd724..f477d17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,25 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [v3.1.0-SNAPSHOT] - 2022-11-30 +## [v3.2.0-SNAPSHOT] - 2022-02-09 - [#24166] Implemented the Update facility - [#24244] Integrated with the geoportal-data-mapper library +## [v3.1.0-SNAPSHOT] - 2023-02-09 + +#### Enhancements + +- [#24569] The Edit operation is available only in the "DRAFT" phase +- [#24571] The "Create Relation" operation is available only in the "DRAFT" phase + +## [v3.0.2] - 2023-02-02 + +#### Fixes + +- [#24520] Added parameter "force=true" to Delete Project +- [#24475] Propagated the Access Policy in the fileset + ## [v3.0.1] - 2023-01-19 #### Fixes @@ -16,7 +30,6 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - [#24281] Fixed filtering selection label - [#24049] Fixed "Show on Map" facility vs Chrome browser - [#24432] Fixing serialization issue using LinkedHashMap instead of LinkedHashMap -- [#24458] Published projects cannot be edited/updated ## [v3.0.0] - 2022-11-09 diff --git a/pom.xml b/pom.xml index 023bc60..ab15f89 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ org.gcube.portlets.user geoportal-data-entry-app war - 3.1.0-SNAPSHOT + 3.2.0-SNAPSHOT GeoPortal Data Entry App The GeoPortal Data Entry App is an application to build the web forms for data entries needed to create projects/documents (based on UCD) in the D4Science Geoportal service diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataentry/client/ConstantsGeoPortalDataEntryApp.java b/src/main/java/org/gcube/portlets/user/geoportaldataentry/client/ConstantsGeoPortalDataEntryApp.java index 7dde208..5fdcf17 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataentry/client/ConstantsGeoPortalDataEntryApp.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataentry/client/ConstantsGeoPortalDataEntryApp.java @@ -3,6 +3,7 @@ package org.gcube.portlets.user.geoportaldataentry.client; import java.util.Arrays; import java.util.List; +import org.gcube.application.geoportalcommon.shared.geoportal.WORKFLOW_PHASE; import org.gcube.application.geoportalcommon.shared.geoportal.ucd.GEOPORTAL_DATA_HANDLER; import org.gcube.application.geoportalcommon.shared.geoportal.ucd.HandlerDeclarationDV; import org.gcube.application.geoportalcommon.shared.geoportal.ucd.UseCaseDescriptorDV; @@ -44,11 +45,21 @@ public class ConstantsGeoPortalDataEntryApp { public static final RootPanel ROOT_PANEL_DIV_PORTLET = RootPanel.get(ConstantsGeoPortalDataEntryApp.DIV_PORTLET_ID); public static final String CSS_CLASS_GEOPORTAL_LOADERS_CENTER = "geoportal-loaders-center"; - + public static final String WORKFLOW_ACTION_POST_CREATION_ACTION_ID = "post_creation_action"; - + public static final DateTimeFormat DATE_TIME_FORMAT = DateTimeFormat.getFormat("dd MMMM yyyy"); + public static final String ALERT_MESSAGE_PROJECT_NOT_EDITABLE = "A Project can only be edited/updated in " + + WORKFLOW_PHASE.DRAFT.name() + + " phase. You need to perform the step 'Reject' or 'UnPublish' to take back the project in " + + WORKFLOW_PHASE.DRAFT.name() + " phase."; + + public static final String ALERT_MESSAGE_CREATE_RELATION_FORBIDDEN = "The Create Relation operation can be performed only in " + + WORKFLOW_PHASE.DRAFT.name() + + " phase. You need to perform the step 'Reject' or 'UnPublish' to take back the project in " + + WORKFLOW_PHASE.DRAFT.name() + " phase."; + /** * The Enum ACTION_PERFORMED_ON_ITEM. * diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataentry/client/GeoPortalDataEntryApp.java b/src/main/java/org/gcube/portlets/user/geoportaldataentry/client/GeoPortalDataEntryApp.java index a51ed6a..d4bfdc6 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataentry/client/GeoPortalDataEntryApp.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataentry/client/GeoPortalDataEntryApp.java @@ -1530,18 +1530,22 @@ public class GeoPortalDataEntryApp implements EntryPoint { modal3.setHeight(height + "px"); - boolean isPublishedProject = false; - - if(resultDocumentDV.getLifecycleInfo()!=null) { + //#24569 + boolean isNotInDRAFT = false; + + if (resultDocumentDV.getLifecycleInfo() != null) { String phase = resultDocumentDV.getLifecycleInfo().getPhase(); - if(phase!=null && phase.compareToIgnoreCase(WORKFLOW_PHASE.PUBLISHED.getLabel())==0) { - - Alert alert = new Alert("A '"+WORKFLOW_PHASE.PUBLISHED.getLabel()+"' project cannot be updated."); + // IF the project is not in DRAFT phase, showing an alert and no Update Mode will + // be activated + if (phase != null && phase.compareToIgnoreCase(WORKFLOW_PHASE.DRAFT.getLabel()) != 0) { + + Alert alert = new Alert( + ConstantsGeoPortalDataEntryApp.ALERT_MESSAGE_PROJECT_NOT_EDITABLE); alert.setType(AlertType.WARNING); alert.setClose(false); modal3.add(alert); - - isPublishedProject = true; + + isNotInDRAFT = true; } } @@ -1556,7 +1560,7 @@ public class GeoPortalDataEntryApp implements EntryPoint { UpdateRecord ur = new UpdateRecord(appManagerBus, resultDocumentDV.getProfileID(), resultDocumentDV.getId()); - if(isPublishedProject) { + if(isNotInDRAFT) { ur.noUpdateMode(); } @@ -1567,7 +1571,28 @@ public class GeoPortalDataEntryApp implements EntryPoint { } case CREATE_RELATION: { - mainTabPanel.showCreateRelationPanel(true, resultDocumentDV); + //#24571 + boolean isNotInDRAFT = false; + + if (resultDocumentDV.getLifecycleInfo() != null) { + String phase = resultDocumentDV.getLifecycleInfo().getPhase(); + // IF the project is not in DRAFT, showing an alert and the no Update Mode will + // be activated + if (phase != null && phase.compareToIgnoreCase(WORKFLOW_PHASE.DRAFT.getLabel()) != 0) { + + String msg = ConstantsGeoPortalDataEntryApp.ALERT_MESSAGE_CREATE_RELATION_FORBIDDEN; + ModalWindow modalW = new ModalWindow(new Image(Images.ICONS.accessDenied()), + "Forbidden: " + action, msg, AlertType.WARNING); + modalW.show(); + + isNotInDRAFT = true; + } + } + + //Allowing the Create Relation only in DRAFT phase + if (!isNotInDRAFT) { + mainTabPanel.showCreateRelationPanel(true, resultDocumentDV); + } break; } diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataentry/client/ui/relation/ViewRelationshipPanel.java b/src/main/java/org/gcube/portlets/user/geoportaldataentry/client/ui/relation/ViewRelationshipPanel.java index ce9d4cc..7b878ed 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataentry/client/ui/relation/ViewRelationshipPanel.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataentry/client/ui/relation/ViewRelationshipPanel.java @@ -140,7 +140,7 @@ public class ViewRelationshipPanel extends Composite { secondProjectPanelContainer.clear(); this.fromTheProject = project; - Entry firstEntrySet = project.getFirstEntryOfMap(); + Entry firstEntrySet = project.getFirstEntryOfMap(); String htmlMsg = firstEntrySet.getKey() + ": " + firstEntrySet.getValue() + " (id: " + project.getId() + ")"; @@ -203,7 +203,7 @@ public class ViewRelationshipPanel extends Composite { @Override public void onSuccess(ResultDocumentDV result) { mapOfTargetProjectForId.put(relationDV.getTargetUCD(), result); - Entry firstEntrySet = result.getFirstEntryOfMap(); + Entry firstEntrySet = result.getFirstEntryOfMap(); String htmlMsg = firstEntrySet.getKey() + ": " + firstEntrySet.getValue() + " (id: " + result.getId() + ")"; diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataentry/server/GeoportalDataEntryServiceImpl.java b/src/main/java/org/gcube/portlets/user/geoportaldataentry/server/GeoportalDataEntryServiceImpl.java index b0296c6..3d46476 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataentry/server/GeoportalDataEntryServiceImpl.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataentry/server/GeoportalDataEntryServiceImpl.java @@ -21,11 +21,14 @@ import org.apache.commons.io.FileUtils; import org.bson.Document; import org.gcube.application.geoportal.client.utils.Serialization; import org.gcube.application.geoportal.common.model.document.Project; +import org.gcube.application.geoportal.common.model.document.access.Access; +import org.gcube.application.geoportal.common.model.document.access.AccessPolicy; import org.gcube.application.geoportal.common.model.document.lifecycle.LifecycleInformation; import org.gcube.application.geoportal.common.model.rest.TempFile; import org.gcube.application.geoportal.common.model.useCaseDescriptor.RelationshipDefinition; import org.gcube.application.geoportal.common.model.useCaseDescriptor.UseCaseDescriptor; import org.gcube.application.geoportal.common.utils.StorageUtils; +import org.gcube.application.geoportalcommon.ConvertToDataServiceModel; import org.gcube.application.geoportalcommon.ConvertToDataValueObjectModel; import org.gcube.application.geoportalcommon.GeoportalCommon; import org.gcube.application.geoportalcommon.ProjectDVBuilder; @@ -78,6 +81,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.gwt.user.server.rpc.RemoteServiceServlet; +import com.jayway.jsonpath.JsonPath; +import com.jayway.jsonpath.spi.json.JsonOrgJsonProvider; /** * The server side implementation of the RPC service. @@ -240,6 +245,8 @@ public class GeoportalDataEntryServiceImpl extends RemoteServiceServlet implemen sectionJSONPathIndexer = new HashMap(); } + String theJSONDocument = theProject.getTheDocument().toJson(); + for (Tree_Node treeNodeChild_GNA_DO : tree_Node.getChildren()) { LOG.debug("Going to upload the files of tree node: " + treeNodeChild_GNA_DO); @@ -332,20 +339,23 @@ public class GeoportalDataEntryServiceImpl extends RemoteServiceServlet implemen File[] fileset = uploadedFileset.getFileset(); FilePathDV filePath = uploadedFileset.getFilePathDV(); + Access access; // If the maxOccurs is not 1 if (profile.getMaxOccurs() == 0 || profile.getMaxOccurs() > 1) { LOG.info("The gCube Profile with the section " + sectionJSONPath + " has maxOccurs > 1 need to manage it as array, going to add the array index"); String arraySectionJSONPAth = String.format("%s[%d]", sectionJSONPath, jpcV); LOG.debug("registering the fileset in the array section: " + sectionJSONPath); + + access = ConvertToDataServiceModel.getAccessFromDocumentSection(theJSONDocument,arraySectionJSONPAth); mongoService.registerFileSet(profileID, theProject, arraySectionJSONPAth, - filePath.getFieldName(), filePath.getFieldDefinition(), fileset); + filePath.getFieldName(), filePath.getFieldDefinition(), access, fileset); } else { LOG.info("The gCube Profile with the section " + sectionJSONPath + " has maxOccurs = 1"); LOG.debug("registering the fileset in the section: " + sectionJSONPath); - + access = ConvertToDataServiceModel.getAccessFromDocumentSection(theJSONDocument,sectionJSONPath); mongoService.registerFileSet(profileID, theProject, sectionJSONPath, filePath.getFieldName(), - filePath.getFieldDefinition(), fileset); + filePath.getFieldDefinition(), access, fileset); } } @@ -523,26 +533,26 @@ public class GeoportalDataEntryServiceImpl extends RemoteServiceServlet implemen searchedData.setTotalItems(totalProjectForProfile); LOG.info("Total Docs read from config: " + totalProjectForProfile); - + // Saving client PROJECTION LinkedHashMap originalProjection = filter.getProjection(); int totalItems = totalProjectForProfile; - //PERFORMING FIRST QUERY FOR IDS IF AND ONLY IF WHERE CONDITIONS IN THE QUERY. - //SEARCHING FACILITY IS ENACTING. - if(filter.getConditions()!=null) { - + // PERFORMING FIRST QUERY FOR IDS IF AND ONLY IF WHERE CONDITIONS IN THE QUERY. + // SEARCHING FACILITY IS ENACTING. + if (filter.getConditions() != null) { + // Setting PROJECTION ONLY FOR PROEJCT ID LinkedHashMap projectionForIDs = new LinkedHashMap(); projectionForIDs.put(Project.ID, 1); filter.setProjection(projectionForIDs); - + // FIRST QUERY TO RETRIEVE IDs // LIMIT IS NULL MEANS THAT IT IS EQUAL TO NUMBER TOTAL OF DOCUMENTS - //Calculating always the size starting from 0 + // Calculating always the size starting from 0 final Iterator projectsIDs = client.queryOnMongo(theProfileID, totalProjectForProfile, 0, null, filter); - - //Getting the Project IDs from the Iterable + + // Getting the Project IDs from the Iterable Iterable itP = () -> projectsIDs; Stream targetStream = StreamSupport.stream(itP.spliterator(), false); List listProjectIDs = targetStream.map(Project::getId).collect(Collectors.toList()); @@ -550,13 +560,12 @@ public class GeoportalDataEntryServiceImpl extends RemoteServiceServlet implemen searchedData.setTotalItems(totalItems); LOG.info("Total Docs read from query per ID: " + totalItems); } - - //NOW PERFORMING THE (REAL) SECOND QUERY FROM CLIENT + + // NOW PERFORMING THE (REAL) SECOND QUERY FROM CLIENT // SETTING ORIGINAL PROJECTION FROM CLIENT filter.setProjection(originalProjection); // LIMIT IS FROM CLIENT - Iterator projects = client.queryOnMongo(theProfileID, totalItems, start, limit, - filter); + Iterator projects = client.queryOnMongo(theProfileID, totalItems, start, limit, filter); searchedData.setClientStartIndex(start); searchedData.setLimit(limit); @@ -564,9 +573,10 @@ public class GeoportalDataEntryServiceImpl extends RemoteServiceServlet implemen List toReturnList = ConvertToDataValueObjectModel.toListResultDocument(projects); searchedData.setData(toReturnList); - - LOG.info("Total Docs page size returned:" + toReturnList.size() + ", start: " + start + ", limit: " + limit); - + + LOG.info( + "Total Docs page size returned:" + toReturnList.size() + ", start: " + start + ", limit: " + limit); + if (totalProjectForProfile == limit || totalProjectForProfile == 0) { LOG.debug("Page completed returning " + totalProjectForProfile + " projects"); int newOffset = start + limit; @@ -612,7 +622,7 @@ public class GeoportalDataEntryServiceImpl extends RemoteServiceServlet implemen ProjectsCaller client = GeoportalClientCaller.projects(); SessionUtil.getCurrentContext(getThreadLocalRequest(), true); - client.deleteProject(profileID, projectID, false); + client.deleteProject(profileID, projectID, true); // Updating count of Documents in session per profileID Integer totalProjectForProfile = client.getTotalDocument(profileID); SessionUtil.setTotalDocumentForProfileID(getThreadLocalRequest(), profileID, totalProjectForProfile); diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataentry/server/MongoServiceUtil.java b/src/main/java/org/gcube/portlets/user/geoportaldataentry/server/MongoServiceUtil.java index 066f1ec..7494cf8 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataentry/server/MongoServiceUtil.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataentry/server/MongoServiceUtil.java @@ -15,6 +15,7 @@ import org.bson.Document; import org.gcube.application.geoportal.client.utils.Serialization; import org.gcube.application.geoportal.common.faults.InvalidRequestException; import org.gcube.application.geoportal.common.model.document.Project; +import org.gcube.application.geoportal.common.model.document.access.Access; import org.gcube.application.geoportal.common.model.rest.RegisterFileSetRequest; import org.gcube.application.geoportal.common.model.rest.TempFile; import org.gcube.application.geoportal.common.rest.MongoConcessioni; @@ -63,7 +64,7 @@ public class MongoServiceUtil { } public void registerFileSet(String profileID, Project project, String parentPath, String fieldName, - String fieldDefinition, File... files) + String fieldDefinition, Access access, File... files) throws RemoteException, FileNotFoundException, JsonProcessingException, InvalidRequestException { LOG.debug("registerFileSet called for profileID: " + profileID); @@ -71,6 +72,8 @@ public class MongoServiceUtil { // Prepare request RegisterFileSetRequest fsRequest = FileSets.prepareRequest(new StorageUtils(), parentPath, fieldName, fieldDefinition, files); + fsRequest.setToSetAccess(access); + project = client.registerFileSet(project.getId(), fsRequest); LOG.trace("Resulting Project : " + project); LOG.debug("Resulting Project as JSON: " + Serialization.write(project));