Skip to content

Commit

Permalink
Merge pull request #897 from AtlasOfLivingAustralia/896-filtes-for-sp…
Browse files Browse the repository at this point in the history
…ecies-image-service

#896 allow preference filters for SpeciesImageService
  • Loading branch information
adam-collins authored Apr 12, 2024
2 parents 7ed6bc3 + 8cd3f5b commit a1afefb
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 41 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ dependencies {

} else {

implementation 'au.org.ala:ala-ws-spring-security:6.2.0'
implementation 'au.org.ala:ala-ws-spring-security:6.3.0-SNAPSHOT'
}

implementation 'org.codehaus.groovy:groovy-all:3.0.11'
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/au/org/ala/biocache/config/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@

import org.pac4j.core.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.core.GrantedAuthorityDefaults;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.inject.Inject;
Expand All @@ -37,4 +39,9 @@ protected void configure(HttpSecurity http) throws Exception {
).permitAll()
.and().csrf().disable();
}

@Bean
public GrantedAuthorityDefaults grantedAuthorityDefaults() {
return new GrantedAuthorityDefaults("");
}
}
73 changes: 50 additions & 23 deletions src/main/java/au/org/ala/biocache/service/SpeciesImageService.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import au.org.ala.biocache.util.SearchUtils;
import au.org.ala.biocache.util.solr.FieldMappingUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.util.SimpleOrderedMap;
Expand All @@ -31,10 +32,7 @@
import org.springframework.stereotype.Component;

import javax.inject.Inject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;

/**
* cache of lft with the first found image info; data_resource_uid, image_url and number found.
Expand Down Expand Up @@ -81,27 +79,26 @@ public void run() {
params.setFl(OccurrenceIndex.DATA_RESOURCE_UID + "," + OccurrenceIndex.IMAGE_URL);
params.setQ(OccurrenceIndex.IMAGE_URL + ":*");

QueryResponse qr = searchDAO.searchGroupedFacets(params);
String [] requiredFqsArray = new String[0];
if (StringUtils.isNotEmpty(requiredFqs)) {
requiredFqsArray = requiredFqs.split(",");
params.setFq(requiredFqsArray);
}

String [] preferredFqsArray = new String[0];
if (StringUtils.isNotEmpty(preferredFqs)) {
preferredFqsArray = preferredFqs.split(",");
}

// fill map with reverse priority search so lower priority entries are overridden by higher priorities
Map<Long, SpeciesImageDTO> map = new HashMap();

for (SimpleOrderedMap item : SearchUtils.getList(qr.getResponse(), "facets", OccurrenceIndex.LFT, "buckets")) {
String dataResourceUid = (String) SearchUtils.getVal(item, OccurrenceIndex.DATA_RESOURCE_UID, "buckets", 0, 0);
String imageUrl = (String) SearchUtils.getVal(item, OccurrenceIndex.IMAGE_URL, "buckets", 0, 0);
SpeciesImageDTO image = new SpeciesImageDTO(dataResourceUid, imageUrl);
if (item.getVal(1) instanceof Integer) {
image.setCount(((Integer) item.getVal(1)).longValue());
} else if (item.getVal(1) instanceof Long){
image.setCount((Long) item.getVal(1));
}
try {
if (item.getVal(0) instanceof Integer) {
map.put(((Integer) item.getVal(0)).longValue(), image);
} else if(item.getVal(0) instanceof Long) {
map.put((Long) item.getVal(0), image);
}
} catch (Exception e) {
}
fillMap(map, params); // request with no preferredFq

String [] fqs = Arrays.copyOf(requiredFqsArray, requiredFqsArray.length + 1);
for (int i = preferredFqsArray.length - 1; i >= 0; i--) {
fqs[fqs.length - 1] = preferredFqsArray[i];
params.setFq(fqs);
fillMap(map, params);
}

//sort keys
Expand Down Expand Up @@ -135,6 +132,28 @@ public void run() {
}
}

private void fillMap(Map<Long, SpeciesImageDTO> map, SpatialSearchRequestDTO params) throws Exception {
QueryResponse qr = searchDAO.searchGroupedFacets(params);
for (SimpleOrderedMap item : SearchUtils.getList(qr.getResponse(), "facets", OccurrenceIndex.LFT, "buckets")) {
String dataResourceUid = (String) SearchUtils.getVal(item, OccurrenceIndex.DATA_RESOURCE_UID, "buckets", 0, 0);
String imageUrl = (String) SearchUtils.getVal(item, OccurrenceIndex.IMAGE_URL, "buckets", 0, 0);
SpeciesImageDTO image = new SpeciesImageDTO(dataResourceUid, imageUrl);
if (item.getVal(1) instanceof Integer) {
image.setCount(((Integer) item.getVal(1)).longValue());
} else if (item.getVal(1) instanceof Long){
image.setCount((Long) item.getVal(1));
}
try {
if (item.getVal(0) instanceof Integer) {
map.put(((Integer) item.getVal(0)).longValue(), image);
} else if(item.getVal(0) instanceof Long) {
map.put((Long) item.getVal(0), image);
}
} catch (Exception e) {
}
}
}

@EventListener(ApplicationReadyEvent.class)
public void init() {
resetCache();
Expand All @@ -146,6 +165,14 @@ public void init() {
@Value("${autocomplete.species.images.enabled:true}")
private Boolean enabled;

// images.preferredFilters=data_resource_uid:dr660 OR data_resource_uid:dr413,-record_type:PreservedSpecimen
@Value("${images.preferredFqs:}")
private String preferredFqs;

// images.requiredFilters=spatiallyValid:true,-user_assertions:50001,-user_assertions:50005
@Value("${images.requiredFqs:}")
private String requiredFqs;

/**
* retrieve left + count + index version
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ List<QualityAssertion> getAssertionQueries(
}

@SecurityRequirement(name="JWT")
@Secured({"ROLE_ADMIN"})
@Secured({"ROLE_ADMIN", "ala/internal"})
@Operation(summary = "Synchronise assertions into the index", tags = "Monitoring")
@RequestMapping(value = {"/sync"}, method = RequestMethod.GET)
public @ResponseBody Boolean indexAll(HttpServletRequest request,
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/au/org/ala/biocache/web/DownloadController.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public class DownloadController extends AbstractSecureController {
*/
@Deprecated
@SecurityRequirement(name="JWT")
@Secured({"ROLE_ADMIN"})
@Secured({"ROLE_ADMIN", "ala/internal"})
@Operation(summary = "Retrieves all the downloads that are on the queue", tags = "Monitoring")
@RequestMapping(value = {"occurrences/offline/download/stats"}, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody Map<String, List<DownloadStatusDTO>> getCurrentDownloads() throws Exception {
Expand Down Expand Up @@ -257,7 +257,7 @@ private DownloadStatusDTO download(DownloadRequestDTO requestParams,
}

@SecurityRequirement(name="JWT")
@Secured({"ROLE_ADMIN"})
@Secured({"ROLE_ADMIN", "ala/internal"})
@Operation(summary = "List all occurrence downloads", tags = "Monitoring")
@RequestMapping(value = {"occurrences/offline/status/all"}, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody Map<String, List<DownloadStatusDTO>> allOccurrenceDownloadStatus() {
Expand All @@ -270,7 +270,7 @@ private DownloadStatusDTO download(DownloadRequestDTO requestParams,
}

@SecurityRequirement(name="JWT")
@Secured({"ROLE_USER"})
@Secured({"ROLE_USER", "ala/internal"})
@Operation(summary = "List all occurrence downloads by the current user", tags = "Monitoring")
@RequestMapping(value = {"occurrences/offline/status"}, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody Map<String, List<DownloadStatusDTO>> allOccurrenceDownloadStatusForUser(
Expand Down Expand Up @@ -410,7 +410,7 @@ private DownloadStatusDTO getOtherStatus(String id) {
* @throws Exception
*/
@SecurityRequirement(name="JWT")
@Secured({"ROLE_USER"})
@Secured({"ROLE_USER", "ala/internal"})
@Operation(summary = "Cancel an offline download", tags = "Monitoring")
@RequestMapping(value = {"occurrences/offline/cancel/{id}"}, method = RequestMethod.GET)
@ApiParam(value = "id", required = true)
Expand Down
14 changes: 7 additions & 7 deletions src/main/java/au/org/ala/biocache/web/OccurrenceController.java
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ Map emptyJson() {
return map;
}

@Secured({"ROLE_ADMIN"})
@Secured({"ROLE_ADMIN", "ala/internal"})
@SecurityRequirement(name = "JWT")
@Operation(summary = "Get list of current downloads", tags = "Monitoring")
@Tag(name = "Monitoring", description = "Admin services for monitoring the application, download stats, and index. Protected APIs require administrative role for access.")
Expand Down Expand Up @@ -525,7 +525,7 @@ public void getIndexedFields(
* @return
* @throws Exception
*/
@Secured({"ROLE_ADMIN"})
@Secured({"ROLE_ADMIN", "ala/internal"})
@SecurityRequirement(name = "JWT")
@Operation(summary = "Show index version information", tags = "Monitoring")
@RequestMapping(value = {"index/version"}, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
Expand All @@ -549,7 +549,7 @@ Map getIndexedFields(@RequestParam(value = "force", required = false, defaultVal
* @return
* @throws Exception
*/
@Secured({"ROLE_ADMIN"})
@Secured({"ROLE_ADMIN", "ala/internal"})
@SecurityRequirement(name = "JWT")
@Operation(summary = "Show configured max boolean clauses", tags = "Monitoring")
@RequestMapping(value = {
Expand All @@ -562,23 +562,23 @@ Map getIndexedFields(@RequestParam(value = "force", required = false, defaultVal
return map;
}


@Secured({"ala/internal"})
@Secured({"ROLE_ADMIN", "ala/internal"})
@SecurityRequirement(name = "JWT")
@Operation(summary = "Export of lft,image", tags = "Monitoring")
@RequestMapping(value = {"index/speciesImages"}, method = RequestMethod.GET)
public @ResponseBody SpeciesImagesDTO getSpeciesImages() {
return speciesImageService.getSpeciesImages();
}

@Secured({"ROLE_ADMIN", "ala/internal"})
@SecurityRequirement(name = "JWT")
@Operation(summary = "Export of lft,count", tags = "Monitoring")
@RequestMapping(value = {"index/speciesOccurrences"}, method = RequestMethod.GET)
public @ResponseBody SpeciesCountDTO getSpeciesCounts() {
return speciesCountsService.getCounts(null);
}

@Secured({"ROLE_ADMIN"})
@Secured({"ROLE_ADMIN", "ala/internal"})
@SecurityRequirement(name = "JWT", scopes = {"ROLE_ADMIN"})
@Operation(summary = "Show configuration", tags = "Monitoring",
description = " Public service that reports limits and other useful config for clients."
Expand Down Expand Up @@ -951,7 +951,7 @@ SearchResultDTO occurrenceSearch(
* @return
* @throws Exception
*/
@Secured({"ROLE_ADMIN"})
@Secured({"ROLE_ADMIN", "ala/internal"})
@SecurityRequirement(name = "JWT")
@Operation(summary = "Refresh caches", tags = "Monitoring")
@RequestMapping(value = {"/cache/refresh"}, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/au/org/ala/biocache/web/WMSController.java
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,7 @@ public SearchResultDTO occurrences(
* @throws Exception
*/
@SecurityRequirement(name="JWT")
@Secured({"ROLE_USER", "ROLE_ADMIN"})
@Secured({"ROLE_USER", "ROLE_ADMIN", "ala/internal"})
@Operation(summary = "Get occurrences by query as gzipped csv.", tags = "Deprecated")
@Deprecated
@RequestMapping(value = {
Expand Down Expand Up @@ -1516,8 +1516,8 @@ public void generateWmsTileViaHeatmap(
List<LegendItem> legend = searchDAO.getColours(requestParams, vars.colourMode);

// Increase size of area requested to include occurrences around the edge that overlap with the target area when drawn.
double bWidth = ((bbox[2] - bbox[0]) / (double) width) * (Math.max(wmsMaxPointWidth, pointWidth) + additionalBuffer);
double bHeight = ((bbox[3] - bbox[1]) / (double) height) * (Math.max(wmsMaxPointWidth, pointWidth) + additionalBuffer);
double bWidth = isGrid ? 0 : ((bbox[2] - bbox[0]) / (double) width) * (Math.max(wmsMaxPointWidth, pointWidth) + additionalBuffer);
double bHeight = isGrid ? 0 : ((bbox[3] - bbox[1]) / (double) height) * (Math.max(wmsMaxPointWidth, pointWidth) + additionalBuffer);

// faster method
HeatmapDTO heatmapDTO = searchDAO.getHeatMap(requestParams.getFormattedQuery(), requestParams.getFormattedFq(), bbox[0] - bWidth, bbox[1] - bHeight, bbox[2] + bWidth, bbox[3] + bHeight, legend, isGrid ? (int) Math.ceil(width / (double) gridDivisionCount) : 1);
Expand Down
9 changes: 8 additions & 1 deletion src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ application-version = 3.0
application-title = Occurrence services
application-terms-url = https://www.ala.org.au

# Use default values
security.oidc.enabled=false
security.jwt.enabled=false

#spring.security.jwt.enabled = true
#spring.security.jwt.jwk.url = https://auth-dev.ala.org.au/cas/oidc/jwks
#spring.security.legacy.apikey.serviceUrl = https://auth-test.ala.org.au/apikey/ws/check?apikey=
Expand All @@ -25,4 +29,7 @@ spring.autoconfigure.exclude = org.springframework.boot.autoconfigure.web.servle
#
#spring.security.user.name=admin
#spring.security.user.password=admin
#spring.security.user.roles=manager
#spring.security.user.roles=manager

# authorized role and scope for JWT authorized requests
admin.roles=ROLE_ADMIN,ala/internal
6 changes: 5 additions & 1 deletion src/test/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,8 @@ spring.security.jwt.jwk.url = https://auth-test.ala.org.au/cas/oidc/jwks
#
#spring.security.user.name=admin
#spring.security.user.password=admin
#spring.security.user.roles=manager
#spring.security.user.roles=manager

# Use default values
security.oidc.enabled=false
security.jwt.enabled=false
2 changes: 2 additions & 0 deletions src/test/resources/biocache-test-config.properties
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,5 @@ webservice.client-secret=changeMe
webservice.jwt-scopes=changeMe
webservices.cache-tokens=true

# Use default values
security.oidc.enabled=false

0 comments on commit a1afefb

Please sign in to comment.