From 6689472e021e105bad8b65d2dda8894880a60d70 Mon Sep 17 00:00:00 2001 From: Ian Allen Date: Thu, 18 Jul 2024 20:12:40 -0300 Subject: [PATCH] Add get /api/sources/{sourceIdentifier} to be able to get a source by id. Moved /api/sources/{type} to Moved /api/sources?type=type as it conflicted with /api/sources/{sourceIdentifier} --- .../geonet/repository/SourceRepository.java | 5 ++- .../fao/geonet/api/sources/SourcesApi.java | 43 ++++++++++++++++--- .../geonet/api/sources/SourcesApiTest.java | 32 ++++++++++++++ .../usersearches/UserSearchesDirective.js | 2 +- .../usersearches/UserSearchesService.js | 2 +- .../catalog/js/admin/CSWTestController.js | 2 +- 6 files changed, 75 insertions(+), 11 deletions(-) diff --git a/domain/src/main/java/org/fao/geonet/repository/SourceRepository.java b/domain/src/main/java/org/fao/geonet/repository/SourceRepository.java index 0ae262662de..c9aee75b83c 100644 --- a/domain/src/main/java/org/fao/geonet/repository/SourceRepository.java +++ b/domain/src/main/java/org/fao/geonet/repository/SourceRepository.java @@ -70,8 +70,11 @@ public interface SourceRepository extends GeonetRepository, JpaS public @Nullable - List findByGroupOwner(@Nonnull int groupOwner); + List findByGroupOwner(@Nonnull int groupOwner, Sort sort); + public + @Nullable + List findByGroupOwnerAndType(@Nonnull int groupOwner, @Nonnull SourceType sourceType, Sort sort); public @Nullable List findByGroupOwnerIn(Set groupOwner); diff --git a/services/src/main/java/org/fao/geonet/api/sources/SourcesApi.java b/services/src/main/java/org/fao/geonet/api/sources/SourcesApi.java index 5b50c543e5c..c968933159a 100644 --- a/services/src/main/java/org/fao/geonet/api/sources/SourcesApi.java +++ b/services/src/main/java/org/fao/geonet/api/sources/SourcesApi.java @@ -33,6 +33,7 @@ import jeeves.server.context.ServiceContext; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; +import org.fao.geonet.api.ApiError; import org.fao.geonet.api.ApiParams; import org.fao.geonet.api.ApiUtils; import org.fao.geonet.api.exception.ResourceNotFoundException; @@ -108,6 +109,10 @@ public ResponseEntity getSources( value = "group", required = false) Integer group, + @RequestParam( + value = "type", + required = false) + SourceType type, @Parameter(hidden = true) HttpServletResponse response, @Parameter(hidden = true) @@ -115,8 +120,12 @@ public ResponseEntity getSources( ) throws Exception { setHeaderVaryOnAccept(response); List sources; - if (group != null) { - sources = sourceRepository.findByGroupOwner(group); + if (group != null && type != null) { + sources = sourceRepository.findByGroupOwnerAndType(group, type, SortUtils.createSort(Source_.name)); + } else if (group != null) { + sources = sourceRepository.findByGroupOwner(group, SortUtils.createSort(Source_.name)); + } else if (type != null) { + sources = sourceRepository.findByType(type, SortUtils.createSort(Source_.name)); } else { sources = sourceRepository.findAll(SortUtils.createSort(Source_.name)); } @@ -145,15 +154,35 @@ private String getSourcesAsHtml(List sources) throws Exception { } @io.swagger.v3.oas.annotations.Operation( - summary = "Get all sources by type", - description = "Sources are the local catalogue, subportal, external catalogue (when importing MEF files) or harvesters.") + summary = "Get a source", + description = "") @RequestMapping( - value = "/{type}", + value = "/{sourceIdentifier}", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET) + @ResponseStatus(HttpStatus.OK) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Source found."), + @ApiResponse(responseCode = "404", description = "Source not found.", + content = @Content(schema = @Schema(implementation = ApiError.class))) + }) @ResponseBody - public List getSourcesByType(@PathVariable SourceType type) throws Exception { - return sourceRepository.findByType(type, SortUtils.createSort(Source_.name)); + public Source getSource( + @Parameter( + description = "Source identifier", + required = true + ) + @PathVariable + String sourceIdentifier) throws Exception { + Optional existingSource = sourceRepository.findById(sourceIdentifier); + if (existingSource.isPresent()) { + return existingSource.get(); + } else { + throw new ResourceNotFoundException(String.format( + "Source with uuid '%s' does not exist.", + sourceIdentifier + )); + } } @io.swagger.v3.oas.annotations.Operation( diff --git a/services/src/test/java/org/fao/geonet/api/sources/SourcesApiTest.java b/services/src/test/java/org/fao/geonet/api/sources/SourcesApiTest.java index 67ac3e74997..9e7ca4b7977 100644 --- a/services/src/test/java/org/fao/geonet/api/sources/SourcesApiTest.java +++ b/services/src/test/java/org/fao/geonet/api/sources/SourcesApiTest.java @@ -70,6 +70,38 @@ public void setUp() throws Exception { createTestData(); } + @Test + public void getSource() throws Exception { + Source source = sourceRepo.findOneByName("source-test"); + Assert.assertNotNull(source); + + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + + this.mockHttpSession = loginAsAdmin(); + + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + this.mockMvc.perform(get("/srv/api/sources/" + source.getUuid()) + .accept(MediaType.parseMediaType("application/json"))) + .andExpect(status().isOk()) + .andExpect(content().contentType(API_JSON_EXPECTED_ENCODING)); + } + + @Test + public void getNonExistingSource() throws Exception { + Source sourceToUpdate = sourceRepo.findOneByName("source-test-2"); + Assert.assertNull(sourceToUpdate); + + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + + this.mockHttpSession = loginAsAdmin(); + + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + this.mockMvc.perform(get("/srv/api/sources/source-test-2") + .accept(MediaType.parseMediaType("application/json"))) + .andExpect(content().contentType(API_JSON_EXPECTED_ENCODING)) + .andExpect(status().is(404)); + } + @Test public void getSources() throws Exception { Long sourcesCount = sourceRepo.count(); diff --git a/web-ui/src/main/resources/catalog/components/usersearches/UserSearchesDirective.js b/web-ui/src/main/resources/catalog/components/usersearches/UserSearchesDirective.js index 32377f5866f..b9e1aacf9a8 100644 --- a/web-ui/src/main/resources/catalog/components/usersearches/UserSearchesDirective.js +++ b/web-ui/src/main/resources/catalog/components/usersearches/UserSearchesDirective.js @@ -39,7 +39,7 @@ gnGlobalSettings.gnCfg.mods.header.showPortalSwitcher; function getPortals() { - var url = "../api/sources/subportal"; + var url = "../api/sources?type=subportal"; $http.get(url).then(function (response) { scope.portals = response.data.filter(function (p) { return p.uuid != scope.nodeId; diff --git a/web-ui/src/main/resources/catalog/components/usersearches/UserSearchesService.js b/web-ui/src/main/resources/catalog/components/usersearches/UserSearchesService.js index dbfae5132f7..52e87c0fe2c 100644 --- a/web-ui/src/main/resources/catalog/components/usersearches/UserSearchesService.js +++ b/web-ui/src/main/resources/catalog/components/usersearches/UserSearchesService.js @@ -35,7 +35,7 @@ usersearches = $http.get("../api/usersearches/featured?type=" + type); var apiCalls = [usersearches]; if (withPortal) { - apiCalls.push($http.get("../api/sources/subportal")); + apiCalls.push($http.get("../api/sources?type=subportal")); } $q.all(apiCalls).then(function (alldata) { var usersearches = []; diff --git a/web-ui/src/main/resources/catalog/js/admin/CSWTestController.js b/web-ui/src/main/resources/catalog/js/admin/CSWTestController.js index ffb95a2409a..a7b606c8e14 100644 --- a/web-ui/src/main/resources/catalog/js/admin/CSWTestController.js +++ b/web-ui/src/main/resources/catalog/js/admin/CSWTestController.js @@ -50,7 +50,7 @@ $scope.cswTests = response.data; }); - $http.get("../api/sources/subportal").then(function (response) { + $http.get("../api/sources?type=subportal").then(function (response) { $scope.cswVirtual = response.data; }); }