From a561bd77c8913a8f061226400e056adae4437578 Mon Sep 17 00:00:00 2001 From: Francois Prunayre Date: Wed, 9 Jun 2021 17:06:28 +0200 Subject: [PATCH] UUID with URL special character support. eg. info:doi:10.24396/ORDAR-56 or http://dada.moo/ORDAR-56 In order to support UUID with character like / or ; in it, you need to disable default Spring HTTP Firewall behaviour which consider those characters unsecure. Error would look like "URL contained a potentially malicious String "%2F"" For this uncomment the firewall configuration in config-security-core.xml and adjust StrictHttpFirewall configuration. Also uncomment the firewall property of filterChainProxy. Client side already URL encode UUIDs and with this, spring will not decode path before matching URL (which would cause issue with request mapping) By default, this is not active. --- .../attachments/FilesystemStoreResource.java | 2 +- .../geonet/api/mapservers/MapServersApi.java | 6 ++--- .../org/fao/geonet/api/records/DoiApi.java | 6 ++--- .../api/records/InspireValidationApi.java | 4 ++-- .../fao/geonet/api/records/MetadataApi.java | 20 +++++++++------- .../api/records/MetadataInsertDeleteApi.java | 2 +- .../api/records/MetadataProcessApi.java | 6 ++--- .../api/records/MetadataSavedQueryApi.java | 2 +- .../api/records/MetadataSharingApi.java | 12 +++++----- .../geonet/api/records/MetadataSocialApi.java | 2 +- .../geonet/api/records/MetadataTagApi.java | 6 ++--- .../api/records/MetadataValidateApi.java | 2 +- .../api/records/MetadataVersionningApi.java | 2 +- .../api/records/MetadataWorkflowApi.java | 20 ++++++++-------- .../attachments/AttachmentsActionsApi.java | 2 +- .../records/attachments/AttachmentsApi.java | 2 +- .../records/editing/MetadataEditingApi.java | 14 +++++------ .../api/records/extent/MetadataExtentApi.java | 6 ++--- .../api/records/formatters/FormatterApi.java | 2 +- .../api/userfeedback/UserFeedbackAPI.java | 6 ++--- .../components/catalog/CatalogService.js | 4 ++-- .../edit/fieldupload/FieldUploadDirective.js | 2 +- .../edit/onlinesrc/OnlineSrcDirective.js | 4 ++-- .../edit/onlinesrc/OnlineSrcService.js | 2 +- .../ValidationReportService.js | 2 +- .../filestore/FileStoreDirective.js | 2 +- .../components/filestore/FileStoreService.js | 2 +- .../metadataactions/MetadataActionService.js | 2 +- .../MetadataActionsDirective.js | 2 +- .../metadataactions/RelatedDirective.js | 2 +- .../search/mdview/mdviewDirective.js | 16 +++++++------ .../search/searchmanager/LocationService.js | 2 +- .../userfeedback/GnUserfeedbackDirective.js | 4 ++-- .../GnmdInspireValidationDirective.js | 2 +- .../directives/partials/mdactionmenu.html | 2 +- .../views/default/templates/recordView.html | 2 +- .../config-security/config-security-core.xml | 24 +++++++++++++++++++ 37 files changed, 114 insertions(+), 86 deletions(-) diff --git a/core/src/main/java/org/fao/geonet/api/records/attachments/FilesystemStoreResource.java b/core/src/main/java/org/fao/geonet/api/records/attachments/FilesystemStoreResource.java index 336cbf4e865..08f665b4c4e 100644 --- a/core/src/main/java/org/fao/geonet/api/records/attachments/FilesystemStoreResource.java +++ b/core/src/main/java/org/fao/geonet/api/records/attachments/FilesystemStoreResource.java @@ -84,7 +84,7 @@ public FilesystemStoreResource(String metadataUuid, @Override public String getId() { - return UrlEscapers.urlFragmentEscaper().escape(metadataUuid) + + return UrlEscapers.urlPathSegmentEscaper().escape(metadataUuid) + "/attachments/" + UrlEscapers.urlFragmentEscaper().escape(filename); } diff --git a/services/src/main/java/org/fao/geonet/api/mapservers/MapServersApi.java b/services/src/main/java/org/fao/geonet/api/mapservers/MapServersApi.java index f09a537da72..961c327b366 100644 --- a/services/src/main/java/org/fao/geonet/api/mapservers/MapServersApi.java +++ b/services/src/main/java/org/fao/geonet/api/mapservers/MapServersApi.java @@ -351,7 +351,7 @@ public void deleteMapserver( // @Authorization(value = "basicAuth") // } ) - @RequestMapping(value = "/{mapserverId}/records/{metadataUuid}", + @RequestMapping(value = "/{mapserverId}/records/{metadataUuid:.+}", method = RequestMethod.GET, produces = { MediaType.TEXT_PLAIN_VALUE @@ -405,7 +405,7 @@ public String getMapserverResource( // @Authorization(value = "basicAuth") // } ) - @RequestMapping(value = "/{mapserverId}/records/{metadataUuid}", + @RequestMapping(value = "/{mapserverId}/records/{metadataUuid:.+}", method = RequestMethod.PUT, produces = { MediaType.TEXT_PLAIN_VALUE @@ -460,7 +460,7 @@ public String publishMapserverResource( // }) ) @RequestMapping( - value = "/{mapserverId}/records/{metadataUuid}", + value = "/{mapserverId}/records/{metadataUuid:.+}", method = RequestMethod.DELETE, produces = { MediaType.TEXT_PLAIN_VALUE diff --git a/services/src/main/java/org/fao/geonet/api/records/DoiApi.java b/services/src/main/java/org/fao/geonet/api/records/DoiApi.java index ed767e39022..47855baef57 100644 --- a/services/src/main/java/org/fao/geonet/api/records/DoiApi.java +++ b/services/src/main/java/org/fao/geonet/api/records/DoiApi.java @@ -69,7 +69,7 @@ public class DoiApi { @io.swagger.v3.oas.annotations.Operation( summary = "Check that a record can be submitted to DataCite for DOI creation. " + "DataCite requires some fields to be populated.") - @RequestMapping(value = "/{metadataUuid}/doi/checkPreConditions", + @RequestMapping(value = "/{metadataUuid:.+}/doi/checkPreConditions", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE @@ -104,7 +104,7 @@ ResponseEntity> checkDoiStatus( @io.swagger.v3.oas.annotations.Operation( summary = "Submit a record to the Datacite metadata store in order to create a DOI.") - @RequestMapping(value = "/{metadataUuid}/doi", + @RequestMapping(value = "/{metadataUuid:.+}/doi", method = RequestMethod.PUT, produces = { MediaType.APPLICATION_JSON_VALUE @@ -141,7 +141,7 @@ ResponseEntity> createDoi( @io.swagger.v3.oas.annotations.Operation( summary = "Remove a DOI (this is not recommended, DOI are supposed to be persistent once created. This is mainly here for testing).") - @RequestMapping(value = "/{metadataUuid}/doi", + @RequestMapping(value = "/{metadataUuid:.+}/doi", method = RequestMethod.DELETE, produces = { MediaType.APPLICATION_JSON_VALUE diff --git a/services/src/main/java/org/fao/geonet/api/records/InspireValidationApi.java b/services/src/main/java/org/fao/geonet/api/records/InspireValidationApi.java index a368a671bd5..8a8dfa43d56 100644 --- a/services/src/main/java/org/fao/geonet/api/records/InspireValidationApi.java +++ b/services/src/main/java/org/fao/geonet/api/records/InspireValidationApi.java @@ -125,7 +125,7 @@ public class InspireValidationApi { @io.swagger.v3.oas.annotations.Operation( summary = "Get test suites available.", description = "TG13, TG2, ...") - @RequestMapping(value = "/{metadataUuid}/validate/inspire/testsuites", + @RequestMapping(value = "/{metadataUuid:.+}/validate/inspire/testsuites", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE @@ -153,7 +153,7 @@ Map getTestSuites( + "An INSPIRE endpoint must be configured in Settings. " + "This activates an asyncronous process, this method does not return any report. " + "This method returns an id to be used to get the report.") - @RequestMapping(value = "/{metadataUuid}/validate/inspire", + @RequestMapping(value = "/{metadataUuid:.+}/validate/inspire", method = RequestMethod.PUT, produces = { MediaType.TEXT_PLAIN_VALUE diff --git a/services/src/main/java/org/fao/geonet/api/records/MetadataApi.java b/services/src/main/java/org/fao/geonet/api/records/MetadataApi.java index 2f6650dd926..9775d93ff37 100644 --- a/services/src/main/java/org/fao/geonet/api/records/MetadataApi.java +++ b/services/src/main/java/org/fao/geonet/api/records/MetadataApi.java @@ -31,6 +31,7 @@ import jeeves.services.ReadWriteController; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; +import org.fao.geonet.Constants; import org.fao.geonet.api.API; import org.fao.geonet.api.ApiParams; import org.fao.geonet.api.ApiUtils; @@ -65,6 +66,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.net.URLEncoder; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; @@ -160,22 +162,22 @@ public String getRecord( List accept = Arrays.asList(acceptHeader.split(",")); String defaultFormatter = "xsl-view"; + String encodedUuid = URLEncoder.encode(metadataUuid, Constants.ENCODING); if (accept.contains(MediaType.TEXT_HTML_VALUE) || accept.contains(MediaType.APPLICATION_XHTML_XML_VALUE) || accept.contains("application/pdf")) { - return "forward:" + (metadataUuid + "/formatters/" + defaultFormatter); + return "redirect:" + (encodedUuid + "/formatters/" + defaultFormatter); } else if (accept.contains(MediaType.APPLICATION_XML_VALUE) || accept.contains(MediaType.APPLICATION_JSON_VALUE)) { - return "forward:" + (metadataUuid + "/formatters/xml"); + return "redirect:" + (encodedUuid + "/formatters/xml"); } else if (accept.contains("application/zip") || accept.contains(MEF_V1_ACCEPT_TYPE) || accept.contains(MEF_V2_ACCEPT_TYPE)) { - return "forward:" + (metadataUuid + "/formatters/zip"); + return "redirect:" + (encodedUuid + "/formatters/zip"); } else { - // FIXME this else is never reached because any of the accepted medias match one of the previous if conditions. response.setHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_XHTML_XML_VALUE); //response.sendRedirect(metadataUuid + "/formatters/" + defaultFormatter); - return "forward:" + (metadataUuid + "/formatters/" + defaultFormatter); + return "redirect:" + (encodedUuid + "/formatters/" + defaultFormatter); } } @@ -184,8 +186,8 @@ public String getRecord( description = "") @RequestMapping(value = { - "/{metadataUuid}/formatters/xml", - "/{metadataUuid}/formatters/json" + "/{metadataUuid:.+}/formatters/xml", + "/{metadataUuid:.+}/formatters/json" }, method = RequestMethod.GET, produces = { @@ -310,7 +312,7 @@ Object getRecordAs( description = "Metadata Exchange Format (MEF) is returned. MEF is a ZIP file containing " + "the metadata as XML and some others files depending on the version requested. " + "See http://geonetwork-opensource.org/manuals/trunk/eng/users/annexes/mef-format.html.") - @RequestMapping(value = "/{metadataUuid}/formatters/zip", + @RequestMapping(value = "/{metadataUuid:.+}/formatters/zip", method = RequestMethod.GET, consumes = { MediaType.ALL_VALUE @@ -549,7 +551,7 @@ public RelatedResponse getAssociatedResources( description = "Retrieve related services, datasets, onlines, thumbnails, sources, ... " + "to this records.
" + "More info") - @RequestMapping(value = "/{metadataUuid}/featureCatalog", + @RequestMapping(value = "/{metadataUuid:.+}/featureCatalog", method = RequestMethod.GET, produces = { MediaType.APPLICATION_XML_VALUE, diff --git a/services/src/main/java/org/fao/geonet/api/records/MetadataInsertDeleteApi.java b/services/src/main/java/org/fao/geonet/api/records/MetadataInsertDeleteApi.java index 96fb5c9176d..380b4be49ee 100644 --- a/services/src/main/java/org/fao/geonet/api/records/MetadataInsertDeleteApi.java +++ b/services/src/main/java/org/fao/geonet/api/records/MetadataInsertDeleteApi.java @@ -168,7 +168,7 @@ public class MetadataInsertDeleteApi { + "By default, a backup is made in ZIP format. After that, " + "the record attachments are removed, the document removed " + "from the index and then from the database.") - @RequestMapping(value = "/{metadataUuid}", method = RequestMethod.DELETE) + @RequestMapping(value = "/{metadataUuid:.+}", method = RequestMethod.DELETE) @ApiResponses(value = {@ApiResponse(responseCode = "204", description = "Record deleted."), @ApiResponse(responseCode = "403", description = ApiParams.API_RESPONSE_NOT_ALLOWED_CAN_EDIT)}) @ResponseStatus(HttpStatus.NO_CONTENT) diff --git a/services/src/main/java/org/fao/geonet/api/records/MetadataProcessApi.java b/services/src/main/java/org/fao/geonet/api/records/MetadataProcessApi.java index f40d2e293b0..4d7a9830a54 100644 --- a/services/src/main/java/org/fao/geonet/api/records/MetadataProcessApi.java +++ b/services/src/main/java/org/fao/geonet/api/records/MetadataProcessApi.java @@ -85,7 +85,7 @@ public class MetadataProcessApi { @io.swagger.v3.oas.annotations.Operation(summary = "Get suggestions", description ="Analyze the record an suggest processes to improve the quality of the record.
" + "More info") - @RequestMapping(value = "/{metadataUuid}/processes", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + @RequestMapping(value = "/{metadataUuid:.+}/processes", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) @PreAuthorize("hasAuthority('Editor')") @ResponseStatus(HttpStatus.OK) @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Record suggestions."), @@ -133,7 +133,7 @@ List getSuggestions( } @io.swagger.v3.oas.annotations.Operation(summary = "Preview process result", description =API_OP_NOTE_PROCESS) - @RequestMapping(value = "/{metadataUuid}/processes/{process:.+}", method = { + @RequestMapping(value = "/{metadataUuid:.+}/processes/{process:.+}", method = { RequestMethod.GET}, produces = MediaType.APPLICATION_XML_VALUE) @PreAuthorize("hasAuthority('Editor')") @ResponseStatus(HttpStatus.OK) @@ -158,7 +158,7 @@ ResponseEntity processRecordPreview( } @io.swagger.v3.oas.annotations.Operation(summary = "Apply a process", description =API_OP_NOTE_PROCESS) - @RequestMapping(value = "/{metadataUuid}/processes/{process:.+}", method = { + @RequestMapping(value = "/{metadataUuid:.+}/processes/{process:.+}", method = { RequestMethod.POST,}, produces = MediaType.APPLICATION_XML_VALUE) @PreAuthorize("hasAuthority('Editor')") @ResponseStatus(HttpStatus.OK) diff --git a/services/src/main/java/org/fao/geonet/api/records/MetadataSavedQueryApi.java b/services/src/main/java/org/fao/geonet/api/records/MetadataSavedQueryApi.java index 071e4e3f6cc..a523d84398f 100644 --- a/services/src/main/java/org/fao/geonet/api/records/MetadataSavedQueryApi.java +++ b/services/src/main/java/org/fao/geonet/api/records/MetadataSavedQueryApi.java @@ -59,7 +59,7 @@ */ @Service @RequestMapping(value = { - "/{portal}/api/records/{metadataUuid}" + "/{portal}/api/records/{metadataUuid:.+}" }) @Tag(name = API_CLASS_RECORD_TAG, description = API_CLASS_RECORD_OPS) diff --git a/services/src/main/java/org/fao/geonet/api/records/MetadataSharingApi.java b/services/src/main/java/org/fao/geonet/api/records/MetadataSharingApi.java index 8170d9de5fa..da4051c4e3d 100644 --- a/services/src/main/java/org/fao/geonet/api/records/MetadataSharingApi.java +++ b/services/src/main/java/org/fao/geonet/api/records/MetadataSharingApi.java @@ -160,7 +160,7 @@ public static Vector retrievePrivileges(ServiceContext conte @io.swagger.v3.oas.annotations.Operation( summary = "Set privileges for ALL group to publish the metadata for all users.") @RequestMapping( - value = "/{metadataUuid}/publish", + value = "/{metadataUuid:.+}/publish", method = RequestMethod.PUT ) @ApiResponses(value = { @@ -187,7 +187,7 @@ public void publish( @io.swagger.v3.oas.annotations.Operation( summary = "Unsets privileges for ALL group to publish the metadata for all users.") @RequestMapping( - value = "/{metadataUuid}/unpublish", + value = "/{metadataUuid:.+}/unpublish", method = RequestMethod.PUT ) @ApiResponses(value = { @@ -223,7 +223,7 @@ public void unpublish( "administrator, a reviewer or the owner of the record.
" + "More info") @RequestMapping( - value = "/{metadataUuid}/sharing", + value = "/{metadataUuid:.+}/sharing", method = RequestMethod.PUT ) @ApiResponses(value = { @@ -453,7 +453,7 @@ private void setOperations( summary = "Get record sharing settings", description = "Return current sharing options for a record.") @RequestMapping( - value = "/{metadataUuid}/sharing", + value = "/{metadataUuid:.+}/sharing", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE ) @@ -549,7 +549,7 @@ public SharingResponse getRecordSharingSettings( summary = "Set record group", description = "A record is related to one group.") @RequestMapping( - value = "/{metadataUuid}/group", + value = "/{metadataUuid:.+}/group", method = RequestMethod.PUT ) @ApiResponses(value = { @@ -738,7 +738,7 @@ MetadataProcessingReport setGroupAndOwner( summary = "Set record group and owner", description = "") @RequestMapping( - value = "/{metadataUuid}/ownership", + value = "/{metadataUuid:.+}/ownership", method = RequestMethod.PUT ) @ResponseStatus(HttpStatus.CREATED) diff --git a/services/src/main/java/org/fao/geonet/api/records/MetadataSocialApi.java b/services/src/main/java/org/fao/geonet/api/records/MetadataSocialApi.java index 364c3c9b8bb..ef7713c3890 100644 --- a/services/src/main/java/org/fao/geonet/api/records/MetadataSocialApi.java +++ b/services/src/main/java/org/fao/geonet/api/records/MetadataSocialApi.java @@ -85,7 +85,7 @@ public class MetadataSocialApi { "When a remote rating is applied, the local rating is not updated. It will be updated on the next " + "harvest run (FIXME ?).") @RequestMapping( - value = "/{metadataUuid}/rate", + value = "/{metadataUuid:.+}/rate", method = RequestMethod.PUT ) @ResponseStatus(HttpStatus.CREATED) diff --git a/services/src/main/java/org/fao/geonet/api/records/MetadataTagApi.java b/services/src/main/java/org/fao/geonet/api/records/MetadataTagApi.java index bcf51b1378f..252a368a758 100644 --- a/services/src/main/java/org/fao/geonet/api/records/MetadataTagApi.java +++ b/services/src/main/java/org/fao/geonet/api/records/MetadataTagApi.java @@ -86,7 +86,7 @@ public class MetadataTagApi { description = "Tags are used to classify information.
" + "More info") @RequestMapping( - value = "/{metadataUuid}/tags", + value = "/{metadataUuid:.+}/tags", produces = { MediaType.APPLICATION_JSON_VALUE }, @@ -114,7 +114,7 @@ public Set getRecordTags( summary = "Add tags to a record", description = "") @RequestMapping( - value = "/{metadataUuid}/tags", + value = "/{metadataUuid:.+}/tags", method = RequestMethod.PUT) @ResponseStatus(value = HttpStatus.CREATED) @ApiResponses(value = { @@ -181,7 +181,7 @@ public void tagRecord( summary = "Delete tags of a record", description = "") @RequestMapping( - value = "/{metadataUuid}/tags", + value = "/{metadataUuid:.+}/tags", method = RequestMethod.DELETE) @ResponseStatus(value = HttpStatus.NO_CONTENT) @ApiResponses(value = { diff --git a/services/src/main/java/org/fao/geonet/api/records/MetadataValidateApi.java b/services/src/main/java/org/fao/geonet/api/records/MetadataValidateApi.java index 0e98aa22866..7930d1e7087 100644 --- a/services/src/main/java/org/fao/geonet/api/records/MetadataValidateApi.java +++ b/services/src/main/java/org/fao/geonet/api/records/MetadataValidateApi.java @@ -152,7 +152,7 @@ public static void restructureReportToHavePatternRuleHierarchy(Element errorRepo @io.swagger.v3.oas.annotations.Operation(summary = "Validate a record", description = "User MUST be able to edit the record to validate it. " + "FIXME : id MUST be the id of the current metadata record in session ?") - @RequestMapping(value = "/{metadataUuid}/validate/internal", method = RequestMethod.PUT, produces = { + @RequestMapping(value = "/{metadataUuid:.+}/validate/internal", method = RequestMethod.PUT, produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}) @ResponseStatus(HttpStatus.CREATED) @PreAuthorize("hasAuthority('Editor')") diff --git a/services/src/main/java/org/fao/geonet/api/records/MetadataVersionningApi.java b/services/src/main/java/org/fao/geonet/api/records/MetadataVersionningApi.java index 5d9442630dd..4a185a93d7e 100644 --- a/services/src/main/java/org/fao/geonet/api/records/MetadataVersionningApi.java +++ b/services/src/main/java/org/fao/geonet/api/records/MetadataVersionningApi.java @@ -72,7 +72,7 @@ public class MetadataVersionningApi { summary = "(Experimental) Enable version control", description = "") @RequestMapping( - value = "/{metadataUuid}/versions", + value = "/{metadataUuid:.+}/versions", method = RequestMethod.PUT) @ResponseStatus(value = HttpStatus.OK) @PreAuthorize("hasAuthority('Editor')") diff --git a/services/src/main/java/org/fao/geonet/api/records/MetadataWorkflowApi.java b/services/src/main/java/org/fao/geonet/api/records/MetadataWorkflowApi.java index 112b5826b2d..c3f85837100 100644 --- a/services/src/main/java/org/fao/geonet/api/records/MetadataWorkflowApi.java +++ b/services/src/main/java/org/fao/geonet/api/records/MetadataWorkflowApi.java @@ -145,7 +145,7 @@ private enum State { @io.swagger.v3.oas.annotations.Operation(summary = "Get record status history", description = "") - @RequestMapping(value = "/{metadataUuid}/status", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET) + @RequestMapping(value = "/{metadataUuid:.+}/status", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET) @ResponseStatus(value = HttpStatus.OK) @ResponseBody public List getRecordStatusHistory( @@ -169,7 +169,7 @@ public List getRecordStatusHistory( } @io.swagger.v3.oas.annotations.Operation(summary = "Get record status history by type", description = "") - @RequestMapping(value = "/{metadataUuid}/status/{type}", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET) + @RequestMapping(value = "/{metadataUuid:.+}/status/{type}", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET) @ResponseStatus(value = HttpStatus.OK) @ResponseBody public List getRecordStatusHistoryByType( @@ -194,7 +194,7 @@ public List getRecordStatusHistoryByType( } @io.swagger.v3.oas.annotations.Operation(summary = "Get last workflow status for a record", description = "") - @RequestMapping(value = "/{metadataUuid}/status/workflow/last", method = RequestMethod.GET, produces = { + @RequestMapping(value = "/{metadataUuid:.+}/status/workflow/last", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE}) @PreAuthorize("hasAuthority('Editor')") @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Record status."), @@ -234,7 +234,7 @@ public MetadataWorkflowStatusResponse getStatus( } @io.swagger.v3.oas.annotations.Operation(summary = "Set the record status", description = "") - @RequestMapping(value = "/{metadataUuid}/status", method = RequestMethod.PUT) + @RequestMapping(value = "/{metadataUuid:.+}/status", method = RequestMethod.PUT) @PreAuthorize("hasAuthority('Editor')") @ApiResponses(value = {@ApiResponse(responseCode = "204", description = "Status updated."), @ApiResponse(responseCode = "400", description = "Metadata workflow not enabled."), @@ -291,7 +291,7 @@ public void setStatus(@Parameter(description = API_PARAM_RECORD_UUID, required = summary = "Close a record task", description = "") @RequestMapping( - value = "/{metadataUuid}/status/{statusId:[0-9]+}.{userId:[0-9]+}.{changeDate}/close", + value = "/{metadataUuid:.+}/status/{statusId:[0-9]+}.{userId:[0-9]+}.{changeDate}/close", method = RequestMethod.PUT ) @PreAuthorize("hasAuthority('Editor')") @@ -321,7 +321,7 @@ public void closeTask(@Parameter(description = API_PARAM_RECORD_UUID, required = } @io.swagger.v3.oas.annotations.Operation(summary = "Delete a record status", description = "") - @RequestMapping(value = "/{metadataUuid}/status/{statusId:[0-9]+}.{userId:[0-9]+}.{changeDate}", method = RequestMethod.DELETE) + @RequestMapping(value = "/{metadataUuid:.+}/status/{statusId:[0-9]+}.{userId:[0-9]+}.{changeDate}", method = RequestMethod.DELETE) @PreAuthorize("hasAuthority('Administrator')") @ApiResponses(value = {@ApiResponse(responseCode = "204", description = "Status removed."), @ApiResponse(responseCode = "404", description = "Status not found."), @@ -348,7 +348,7 @@ public void deleteRecordStatus( } @io.swagger.v3.oas.annotations.Operation(summary = "Delete all record status", description = "") - @RequestMapping(value = "/{metadataUuid}/status", method = RequestMethod.DELETE) + @RequestMapping(value = "/{metadataUuid:.+}/status", method = RequestMethod.DELETE) @PreAuthorize("hasAuthority('Administrator')") @ApiResponses(value = {@ApiResponse(responseCode = "204", description = "Status removed."), @ApiResponse(responseCode = "404", description = "Status not found."), @@ -471,7 +471,7 @@ private MetadataStatus convertParameter(int id, String uuid, MetadataStatusParam summary = "Get saved content from the status record before changes", description = "") @RequestMapping( - value = "/{metadataUuid}/status/{statusId:[0-9]+}.{userId:[0-9]+}.{changeDate}/before", + value = "/{metadataUuid:.+}/status/{statusId:[0-9]+}.{userId:[0-9]+}.{changeDate}/before", method = RequestMethod.GET, produces = { MediaType.APPLICATION_XML_VALUE @@ -501,7 +501,7 @@ public String showStatusBefore( @io.swagger.v3.oas.annotations.Operation( summary = "Get saved content from the status record after changes" ) - @RequestMapping(value = "/{metadataUuid}/status/{statusId:[0-9]+}.{userId:[0-9]+}.{changeDate}/after", + @RequestMapping(value = "/{metadataUuid:.+}/status/{statusId:[0-9]+}.{userId:[0-9]+}.{changeDate}/after", method = RequestMethod.GET, produces = { MediaType.APPLICATION_XML_VALUE @@ -531,7 +531,7 @@ public String showStatusAfter( @io.swagger.v3.oas.annotations.Operation( summary = "Restore saved content from a status record") @RequestMapping( - value = "/{metadataUuid}/status/{statusId:[0-9]+}.{userId:[0-9]+}.{changeDate}/restore", + value = "/{metadataUuid:.+}/status/{statusId:[0-9]+}.{userId:[0-9]+}.{changeDate}/restore", method = RequestMethod.POST ) @PreAuthorize("hasAuthority('Editor')") diff --git a/services/src/main/java/org/fao/geonet/api/records/attachments/AttachmentsActionsApi.java b/services/src/main/java/org/fao/geonet/api/records/attachments/AttachmentsActionsApi.java index 8a259e676cd..331ed9b8199 100644 --- a/services/src/main/java/org/fao/geonet/api/records/attachments/AttachmentsActionsApi.java +++ b/services/src/main/java/org/fao/geonet/api/records/attachments/AttachmentsActionsApi.java @@ -96,7 +96,7 @@ public void init() { //response = MetadataResource.class) ) @RequestMapping( - value = "/{portal}/api/records/{metadataUuid}/attachments/print-thumbnail", + value = "/{portal}/api/records/{metadataUuid:.+}/attachments/print-thumbnail", method = RequestMethod.PUT) @ResponseStatus(HttpStatus.CREATED) @ApiResponses(value = { diff --git a/services/src/main/java/org/fao/geonet/api/records/attachments/AttachmentsApi.java b/services/src/main/java/org/fao/geonet/api/records/attachments/AttachmentsApi.java index 9acd4bceccb..6eb92de5cc6 100644 --- a/services/src/main/java/org/fao/geonet/api/records/attachments/AttachmentsApi.java +++ b/services/src/main/java/org/fao/geonet/api/records/attachments/AttachmentsApi.java @@ -72,7 +72,7 @@ */ @EnableWebMvc @Service -@RequestMapping(value = {"/{portal}/api/records/{metadataUuid}/attachments"}) +@RequestMapping(value = {"/{portal}/api/records/{metadataUuid:.+}/attachments"}) @Tag(name = "records", description = "Metadata record operations") public class AttachmentsApi { public static final Integer MIN_IMAGE_SIZE = 1; diff --git a/services/src/main/java/org/fao/geonet/api/records/editing/MetadataEditingApi.java b/services/src/main/java/org/fao/geonet/api/records/editing/MetadataEditingApi.java index 7685f8db47b..f355e9a376e 100644 --- a/services/src/main/java/org/fao/geonet/api/records/editing/MetadataEditingApi.java +++ b/services/src/main/java/org/fao/geonet/api/records/editing/MetadataEditingApi.java @@ -96,7 +96,7 @@ public class MetadataEditingApi { SchemaManager schemaManager; @io.swagger.v3.oas.annotations.Operation(summary = "Edit a record", description = "Return HTML form for editing.") - @RequestMapping(value = "/{metadataUuid}/editor", method = RequestMethod.GET, consumes = { + @RequestMapping(value = "/{metadataUuid:.+}/editor", method = RequestMethod.GET, consumes = { MediaType.ALL_VALUE}, produces = {MediaType.APPLICATION_XML_VALUE}) @PreAuthorize("hasAuthority('Editor')") @ResponseStatus(HttpStatus.OK) @@ -160,7 +160,7 @@ public void startEditing( } @io.swagger.v3.oas.annotations.Operation(summary = "Save edits", description = "Save the HTML form content.") - @RequestMapping(value = "/{metadataUuid}/editor", method = RequestMethod.POST, consumes = { + @RequestMapping(value = "/{metadataUuid:.+}/editor", method = RequestMethod.POST, consumes = { MediaType.ALL_VALUE}, produces = {MediaType.APPLICATION_XML_VALUE}) @PreAuthorize("hasAuthority('Editor')") @ResponseStatus(HttpStatus.OK) @@ -433,7 +433,7 @@ public void saveEdits( } @io.swagger.v3.oas.annotations.Operation(summary = "Cancel edits", description = "Cancel current editing session.") - @RequestMapping(value = "/{metadataUuid}/editor", method = RequestMethod.DELETE, consumes = { + @RequestMapping(value = "/{metadataUuid:.+}/editor", method = RequestMethod.DELETE, consumes = { MediaType.ALL_VALUE}, produces = {MediaType.APPLICATION_XML_VALUE}) @PreAuthorize("hasAuthority('Editor')") @ResponseStatus(HttpStatus.NO_CONTENT) @@ -452,7 +452,7 @@ public void cancelEdits(@Parameter(description = API_PARAM_RECORD_UUID, required } @io.swagger.v3.oas.annotations.Operation(summary = "Add element", description = "") - @RequestMapping(value = "/{metadataUuid}/editor/elements", method = RequestMethod.PUT, consumes = { + @RequestMapping(value = "/{metadataUuid:.+}/editor/elements", method = RequestMethod.PUT, consumes = { MediaType.ALL_VALUE}, produces = {MediaType.APPLICATION_XML_VALUE}) @PreAuthorize("hasAuthority('Editor')") @ResponseStatus(HttpStatus.OK) @@ -494,7 +494,7 @@ public void addElement(@Parameter(description = API_PARAM_RECORD_UUID, required } @io.swagger.v3.oas.annotations.Operation(summary = "Reorder element", description = "") - @RequestMapping(value = "/{metadataUuid}/editor/elements/{direction}", method = RequestMethod.PUT, consumes = { + @RequestMapping(value = "/{metadataUuid:.+}/editor/elements/{direction}", method = RequestMethod.PUT, consumes = { MediaType.ALL_VALUE}, produces = {MediaType.APPLICATION_XML_VALUE}) @PreAuthorize("hasAuthority('Editor')") @ResponseStatus(HttpStatus.CREATED) @@ -515,7 +515,7 @@ public void addElement(@Parameter(description = API_PARAM_RECORD_UUID, required } @io.swagger.v3.oas.annotations.Operation(summary = "Delete element", description = "") - @RequestMapping(value = "/{metadataUuid}/editor/elements", method = RequestMethod.DELETE, consumes = { + @RequestMapping(value = "/{metadataUuid:.+}/editor/elements", method = RequestMethod.DELETE, consumes = { MediaType.ALL_VALUE}, produces = {MediaType.APPLICATION_XML_VALUE}) @PreAuthorize("hasAuthority('Editor')") @ResponseStatus(HttpStatus.NO_CONTENT) @@ -539,7 +539,7 @@ public void deleteElement( } @io.swagger.v3.oas.annotations.Operation(summary = "Delete attribute", description = "") - @RequestMapping(value = "/{metadataUuid}/editor/attributes", method = RequestMethod.DELETE, consumes = { + @RequestMapping(value = "/{metadataUuid:.+}/editor/attributes", method = RequestMethod.DELETE, consumes = { MediaType.ALL_VALUE}, produces = {MediaType.APPLICATION_XML_VALUE}) @PreAuthorize("hasAuthority('Editor')") @ResponseStatus(HttpStatus.NO_CONTENT) diff --git a/services/src/main/java/org/fao/geonet/api/records/extent/MetadataExtentApi.java b/services/src/main/java/org/fao/geonet/api/records/extent/MetadataExtentApi.java index 4e586398e6b..4b41834c4c2 100644 --- a/services/src/main/java/org/fao/geonet/api/records/extent/MetadataExtentApi.java +++ b/services/src/main/java/org/fao/geonet/api/records/extent/MetadataExtentApi.java @@ -117,7 +117,7 @@ public class MetadataExtentApi { summary = "Get record extents as image", description = API_EXTENT_DESCRIPTION) @RequestMapping( - value = "/{metadataUuid}/extents.png", + value = "/{metadataUuid:.+}/extents.png", produces = { MediaType.IMAGE_PNG_VALUE }, @@ -155,7 +155,7 @@ public HttpEntity getAllRecordExtentAsImage( summary = "Get list of record extents", description = API_EXTENT_DESCRIPTION) @RequestMapping( - value = "/{metadataUuid}/extents.json", + value = "/{metadataUuid:.+}/extents.json", produces = { MediaType.APPLICATION_JSON_VALUE }, @@ -217,7 +217,7 @@ public List getAllRecordExtentAsJson( summary = "Get one record extent as image", description = API_EXTENT_DESCRIPTION) @RequestMapping( - value = "/{metadataUuid}/extents/{geometryIndex}.png", + value = "/{metadataUuid:.+}/extents/{geometryIndex}.png", produces = { MediaType.IMAGE_PNG_VALUE }, diff --git a/services/src/main/java/org/fao/geonet/api/records/formatters/FormatterApi.java b/services/src/main/java/org/fao/geonet/api/records/formatters/FormatterApi.java index ce96ed67083..7ead35ed3da 100644 --- a/services/src/main/java/org/fao/geonet/api/records/formatters/FormatterApi.java +++ b/services/src/main/java/org/fao/geonet/api/records/formatters/FormatterApi.java @@ -166,7 +166,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO } @RequestMapping(value = { - "/{portal}/api/records/{metadataUuid}/formatters/{formatterId}" + "/{portal}/api/records/{metadataUuid:.+}/formatters/{formatterId}" }, method = RequestMethod.GET, produces = { diff --git a/services/src/main/java/org/fao/geonet/api/userfeedback/UserFeedbackAPI.java b/services/src/main/java/org/fao/geonet/api/userfeedback/UserFeedbackAPI.java index 0fc2841e202..1530a6e09cc 100644 --- a/services/src/main/java/org/fao/geonet/api/userfeedback/UserFeedbackAPI.java +++ b/services/src/main/java/org/fao/geonet/api/userfeedback/UserFeedbackAPI.java @@ -173,7 +173,7 @@ public ResponseEntity deleteUserFeedback( * @throws Exception the exception */ @io.swagger.v3.oas.annotations.Operation(summary = "Provides an average rating for a metadata record") - @RequestMapping(value = "/records/{metadataUuid}/userfeedbackrating", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET) + @RequestMapping(value = "/records/{metadataUuid:.+}/userfeedbackrating", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET) @ResponseStatus(value = HttpStatus.OK) @ResponseBody public RatingAverage getMetadataRating( @@ -302,7 +302,7 @@ public UserFeedbackDTO getUserComment( description = " This list will include also the draft user feedback if the client is logged as reviewer." ) @RequestMapping( - value = "/records/{metadataUuid}/userfeedback", + value = "/records/{metadataUuid:.+}/userfeedback", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET) @ResponseStatus(value = HttpStatus.OK) @@ -487,7 +487,7 @@ public ResponseEntity newUserFeedback( summary = "Send an email to catalogue administrator or record's contact", description = "") @RequestMapping( - value = "/records/{metadataUuid}/alert", + value = "/records/{metadataUuid:.+}/alert", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.POST) @ResponseStatus(HttpStatus.CREATED) diff --git a/web-ui/src/main/resources/catalog/components/catalog/CatalogService.js b/web-ui/src/main/resources/catalog/components/catalog/CatalogService.js index 79e5ff760a7..3cdeddc55bc 100644 --- a/web-ui/src/main/resources/catalog/components/catalog/CatalogService.js +++ b/web-ui/src/main/resources/catalog/components/catalog/CatalogService.js @@ -81,7 +81,7 @@ * @return {HttpPromise} Future object */ validate: function(id) { - return $http.put('../api/records/' + id + '/validate/internal'); + return $http.put('../api/records/' + encodeURIComponent(id) + '/validate/internal'); }, /** @@ -98,7 +98,7 @@ */ validateDirectoryEntry: function(id, newState) { var param = '?isvalid=' + (newState ? 'true' : 'false'); - return $http.put('../api/records/' + id + '/validate/internal' + param); + return $http.put('../api/records/' + encodeURIComponent(id) + '/validate/internal' + param); }, /** diff --git a/web-ui/src/main/resources/catalog/components/edit/fieldupload/FieldUploadDirective.js b/web-ui/src/main/resources/catalog/components/edit/fieldupload/FieldUploadDirective.js index be55bce59bd..f4a21a93ca3 100644 --- a/web-ui/src/main/resources/catalog/components/edit/fieldupload/FieldUploadDirective.js +++ b/web-ui/src/main/resources/catalog/components/edit/fieldupload/FieldUploadDirective.js @@ -137,7 +137,7 @@ scope.queue = []; scope.filestoreUploadOptions = { autoUpload: true, - url: '../api/records/' + gnCurrentEdit.uuid + + url: '../api/records/' + encodeURIComponent(gnCurrentEdit.uuid) + '/attachments?visibility=public', dropZone: $('#gn-overview-dropzone'), singleUpload: true, diff --git a/web-ui/src/main/resources/catalog/components/edit/onlinesrc/OnlineSrcDirective.js b/web-ui/src/main/resources/catalog/components/edit/onlinesrc/OnlineSrcDirective.js index c0eef236ac3..78168908b2c 100644 --- a/web-ui/src/main/resources/catalog/components/edit/onlinesrc/OnlineSrcDirective.js +++ b/web-ui/src/main/resources/catalog/components/edit/onlinesrc/OnlineSrcDirective.js @@ -245,7 +245,7 @@ scope.queue = []; scope.filestoreUploadOptions = { autoUpload: true, - url: '../api/records/' + gnCurrentEdit.uuid + + url: '../api/records/' + encodeURIComponent(gnCurrentEdit.uuid) + '/attachments?visibility=public', dropZone: $('#gn-overview-dropzone'), singleUpload: true, @@ -623,7 +623,7 @@ }); return $http.put('../api/records/' + - scope.gnCurrentEdit.uuid + + encodeURIComponent(scope.gnCurrentEdit.uuid) + '/attachments/print-thumbnail', null, { params: { jsonConfig: angular.fromJson(jsonSpec), diff --git a/web-ui/src/main/resources/catalog/components/edit/onlinesrc/OnlineSrcService.js b/web-ui/src/main/resources/catalog/components/edit/onlinesrc/OnlineSrcService.js index 581a744bcfc..a55e3e20173 100644 --- a/web-ui/src/main/resources/catalog/components/edit/onlinesrc/OnlineSrcService.js +++ b/web-ui/src/main/resources/catalog/components/edit/onlinesrc/OnlineSrcService.js @@ -214,7 +214,7 @@ getAllResources: function(types) { var defer = $q.defer(); - var url = '../api/records/' + gnCurrentEdit.uuid + '/related' + + var url = '../api/records/' + encodeURIComponent(gnCurrentEdit.uuid) + '/related' + (angular.isArray(types) ? '?' + types.join('&type=') : ''); $http.get(url, { headers: { diff --git a/web-ui/src/main/resources/catalog/components/edit/validationreport/ValidationReportService.js b/web-ui/src/main/resources/catalog/components/edit/validationreport/ValidationReportService.js index c9fa9d4e6ad..e2554dedc0f 100644 --- a/web-ui/src/main/resources/catalog/components/edit/validationreport/ValidationReportService.js +++ b/web-ui/src/main/resources/catalog/components/edit/validationreport/ValidationReportService.js @@ -35,7 +35,7 @@ return { get: function() { return $http.put( - '../api/records/' + gnCurrentEdit.uuid + '/validate/internal'); + '../api/records/' + encodeURIComponent(gnCurrentEdit.uuid) + '/validate/internal'); }, errorCheck: function() { return this.get() diff --git a/web-ui/src/main/resources/catalog/components/filestore/FileStoreDirective.js b/web-ui/src/main/resources/catalog/components/filestore/FileStoreDirective.js index b8302fb417a..e4ef665a7c1 100644 --- a/web-ui/src/main/resources/catalog/components/filestore/FileStoreDirective.js +++ b/web-ui/src/main/resources/catalog/components/filestore/FileStoreDirective.js @@ -143,7 +143,7 @@ scope.queue = []; scope.filestoreUploadOptions = { autoUpload: scope.autoUpload, - url: '../api/records/' + scope.uuid + + url: '../api/records/' + encodeURIComponent(scope.uuid) + '/attachments?visibility=' + defaultStatus, dropZone: $('#' + scope.id), singleUpload: false, diff --git a/web-ui/src/main/resources/catalog/components/filestore/FileStoreService.js b/web-ui/src/main/resources/catalog/components/filestore/FileStoreService.js index 89b35704aca..d880e0de51d 100644 --- a/web-ui/src/main/resources/catalog/components/filestore/FileStoreService.js +++ b/web-ui/src/main/resources/catalog/components/filestore/FileStoreService.js @@ -34,7 +34,7 @@ return { get: function(metadataUuid, filter) { return $http.get('../api/records/' + - metadataUuid + '/attachments', { + encodeURIComponent(metadataUuid) + '/attachments', { params: { filter: filter, _random: Math.floor(Math.random() * 10000), diff --git a/web-ui/src/main/resources/catalog/components/metadataactions/MetadataActionService.js b/web-ui/src/main/resources/catalog/components/metadataactions/MetadataActionService.js index 8369f62e1b3..2cd8f5c4449 100644 --- a/web-ui/src/main/resources/catalog/components/metadataactions/MetadataActionService.js +++ b/web-ui/src/main/resources/catalog/components/metadataactions/MetadataActionService.js @@ -417,7 +417,7 @@ this.assignCategories = function(metadataId, categories) { var defer = $q.defer(); - $http.get('../records/' + metadataId + + $http.get('../records/' + encodeURIComponent(metadataId) + '/tags?id=' + categories.join('&id=')) .success(function(data) { defer.resolve(data); diff --git a/web-ui/src/main/resources/catalog/components/metadataactions/MetadataActionsDirective.js b/web-ui/src/main/resources/catalog/components/metadataactions/MetadataActionsDirective.js index 2c2a1dd9e73..5b063620f56 100644 --- a/web-ui/src/main/resources/catalog/components/metadataactions/MetadataActionsDirective.js +++ b/web-ui/src/main/resources/catalog/components/metadataactions/MetadataActionsDirective.js @@ -295,7 +295,7 @@ method = 'delete'; } $http[method]('../api/records/' + - scope.metadataUuid + '/tags?id=' + c.id) + encodeURIComponent(scope.metadataUuid) + '/tags?id=' + c.id) .then(function() { if (existIndex === -1) { scope.ids.push(c.id); diff --git a/web-ui/src/main/resources/catalog/components/metadataactions/RelatedDirective.js b/web-ui/src/main/resources/catalog/components/metadataactions/RelatedDirective.js index 130ae5f30b1..37368c9da96 100644 --- a/web-ui/src/main/resources/catalog/components/metadataactions/RelatedDirective.js +++ b/web-ui/src/main/resources/catalog/components/metadataactions/RelatedDirective.js @@ -46,7 +46,7 @@ var canceller = $q.defer(); var request = $http({ method: 'get', - url: '../api/records/' + uuidOrId + '/related?' + + url: '../api/records/' + encodeURIComponent(uuidOrId) + '/related?' + (types ? 'type=' + types.split('|').join('&type=') : ''), diff --git a/web-ui/src/main/resources/catalog/components/search/mdview/mdviewDirective.js b/web-ui/src/main/resources/catalog/components/search/mdview/mdviewDirective.js index 8544fb4715f..bac2053b669 100644 --- a/web-ui/src/main/resources/catalog/components/search/mdview/mdviewDirective.js +++ b/web-ui/src/main/resources/catalog/components/search/mdview/mdviewDirective.js @@ -56,17 +56,19 @@ var hyperlinkTagName = 'A'; if (element.get(0).tagName === hyperlinkTagName) { - var url = window.location.pathname + '#/' + - (scope.md.draft == 'y' ? 'metadraf' : 'metadata') + - '/' + scope.md.uuid + - (scope.formatter === undefined || scope.formatter == '' ? - '' : - formatter); + var url = window.location.pathname + + (window.location.search === '?debug' ? '?debug' : '') + + '#/' + + (scope.md.draft == 'y' ? 'metadraf' : 'metadata') + + '/' + + encodeURIComponent(scope.md.uuid) + + (scope.formatter === undefined || scope.formatter == '' + ? '' : formatter); element.attr('href', url); } else { element.on('click', function(e) { - gnMdView.setLocationUuid(scope.md.uuid, formatter); + gnMdView.setLocationUuid(encodeURIComponent(scope.md.uuid), formatter); }); } if (scope.records && scope.records.length) { diff --git a/web-ui/src/main/resources/catalog/components/search/searchmanager/LocationService.js b/web-ui/src/main/resources/catalog/components/search/searchmanager/LocationService.js index 8365e353cdc..3916fc3f752 100644 --- a/web-ui/src/main/resources/catalog/components/search/searchmanager/LocationService.js +++ b/web-ui/src/main/resources/catalog/components/search/searchmanager/LocationService.js @@ -116,7 +116,7 @@ this.getUuid = function() { if (this.isMdView()) { - return $location.path().split('/')[2]; + return $location.path().replace(/\/metadata\/(.*)($|\/formatters.*)/, '$1'); } }; diff --git a/web-ui/src/main/resources/catalog/components/userfeedback/GnUserfeedbackDirective.js b/web-ui/src/main/resources/catalog/components/userfeedback/GnUserfeedbackDirective.js index 3cc1b15a965..9c359ebaebc 100644 --- a/web-ui/src/main/resources/catalog/components/userfeedback/GnUserfeedbackDirective.js +++ b/web-ui/src/main/resources/catalog/components/userfeedback/GnUserfeedbackDirective.js @@ -48,7 +48,7 @@ var numberOfCommentsDisplayed = size || -1; return $http({ method: 'GET', - url: '../api/records/' + metatdataUUID + + url: '../api/records/' + encodeURIComponent(metatdataUUID) + '/userfeedback?size=' + numberOfCommentsDisplayed, isArray: true }); @@ -57,7 +57,7 @@ this.loadRating = function(metatdataUUID) { return $http({ method: 'GET', - url: '../api/records/' + metatdataUUID + '/userfeedbackrating', + url: '../api/records/' + encodeURIComponent(metatdataUUID) + '/userfeedbackrating', isArray: false }); }; diff --git a/web-ui/src/main/resources/catalog/components/validationtools/GnmdInspireValidationDirective.js b/web-ui/src/main/resources/catalog/components/validationtools/GnmdInspireValidationDirective.js index c0024114e97..80b8d235ed0 100644 --- a/web-ui/src/main/resources/catalog/components/validationtools/GnmdInspireValidationDirective.js +++ b/web-ui/src/main/resources/catalog/components/validationtools/GnmdInspireValidationDirective.js @@ -56,7 +56,7 @@ scope.md = gnCurrentEdit.metadata; $http({ method: 'GET', - url: '../api/records/' + scope.inspMdUuid + + url: '../api/records/' + encodeURIComponent(scope.inspMdUuid) + '/validate/inspire/testsuites' }).then(function(r) { scope.testsuites = r.data; diff --git a/web-ui/src/main/resources/catalog/views/default/directives/partials/mdactionmenu.html b/web-ui/src/main/resources/catalog/views/default/directives/partials/mdactionmenu.html index bf5a709ca65..b8b5f7d306d 100644 --- a/web-ui/src/main/resources/catalog/views/default/directives/partials/mdactionmenu.html +++ b/web-ui/src/main/resources/catalog/views/default/directives/partials/mdactionmenu.html @@ -207,7 +207,7 @@
  • -   {{f.label | translate}} diff --git a/web-ui/src/main/resources/catalog/views/default/templates/recordView.html b/web-ui/src/main/resources/catalog/views/default/templates/recordView.html index 64cd619be05..1ea2d8951f6 100644 --- a/web-ui/src/main/resources/catalog/views/default/templates/recordView.html +++ b/web-ui/src/main/resources/catalog/views/default/templates/recordView.html @@ -531,7 +531,7 @@

    {{'extent' | translate}} + data-ng-src="../api/records/{{mdView.current.record.uuid | encodeURIComponent}}/extents.png"/>

    diff --git a/web/src/main/webapp/WEB-INF/config-security/config-security-core.xml b/web/src/main/webapp/WEB-INF/config-security/config-security-core.xml index 46831cffaad..1e616c3804e 100644 --- a/web/src/main/webapp/WEB-INF/config-security/config-security-core.xml +++ b/web/src/main/webapp/WEB-INF/config-security/config-security-core.xml @@ -63,8 +63,32 @@ + +