-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Server side validation for restricted values #93
Merged
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
abb032a
Initial implementation for #82
jack-brinkman 4fcee79
#93 Removed GSON dependency & switched to ObjectMapper
jack-brinkman b662bda
#93 Added metadata validation to GraphQL controller
jack-brinkman 3daabed
Constraint service now reads JSON from configurable JSON path
jack-brinkman 22f28e4
Countries & states (regions) are now fetched form userdetails
jack-brinkman 8494342
Moved GraphQL list metadata validation check higher
jack-brinkman 864bff5
Improved error message handling in GraphQL controller
jack-brinkman 6dce183
Improved clarity of validation service methods, fixed list validation…
jack-brinkman a904ca8
Removed implementation of local constraints file
jack-brinkman 17c5e2d
Added userdetails & constraints config to application.properties
jack-brinkman 07271ef
Removed requirement for constraining regions
jack-brinkman 40856ac
Removed validation check for region/country
jack-brinkman 22f6245
Merge branch 'develop' into feature/list-validation
jack-brinkman File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
44 changes: 44 additions & 0 deletions
44
lists-service/src/main/java/au/org/ala/listsapi/controller/UtilsController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package au.org.ala.listsapi.controller; | ||
|
||
import au.org.ala.listsapi.model.ConstraintType; | ||
import au.org.ala.listsapi.service.ValidationService; | ||
import io.swagger.v3.oas.annotations.Operation; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.CrossOrigin; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
|
||
@CrossOrigin(origins = "*", maxAge = 3600) | ||
@org.springframework.web.bind.annotation.RestController | ||
public class UtilsController { | ||
@Autowired protected ValidationService validationService; | ||
|
||
@Operation(tags = "REST", summary = "Get all constraint lists") | ||
@GetMapping("/constraints") | ||
public ResponseEntity<Object> constraints() { | ||
try { | ||
return new ResponseEntity<>( | ||
validationService.getConstraintMap(), | ||
HttpStatus.OK | ||
); | ||
} catch (Exception e) { | ||
return ResponseEntity.badRequest().body(e.getMessage()); | ||
} | ||
} | ||
|
||
@Operation(tags = "REST", summary = "Get constraints for list types, licenses, countries") | ||
@GetMapping("/constraints/{type:lists|licenses|countries}") | ||
public ResponseEntity<Object> constraintsForType( | ||
@PathVariable("type") ConstraintType constraintType) { | ||
try { | ||
return new ResponseEntity<>( | ||
validationService.getConstraintList(constraintType), | ||
HttpStatus.OK | ||
); | ||
} catch (Exception e) { | ||
return ResponseEntity.badRequest().body(e.getMessage()); | ||
} | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
lists-service/src/main/java/au/org/ala/listsapi/model/ConstraintListItem.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package au.org.ala.listsapi.model; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Data; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import lombok.experimental.SuperBuilder; | ||
|
||
@Getter | ||
@NoArgsConstructor | ||
@Data | ||
@SuperBuilder | ||
@AllArgsConstructor | ||
public class ConstraintListItem { | ||
private String value; | ||
private String label; | ||
} |
7 changes: 7 additions & 0 deletions
7
lists-service/src/main/java/au/org/ala/listsapi/model/ConstraintType.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package au.org.ala.listsapi.model; | ||
|
||
public enum ConstraintType { | ||
lists, | ||
licenses, | ||
countries, | ||
} |
17 changes: 17 additions & 0 deletions
17
lists-service/src/main/java/au/org/ala/listsapi/model/Location.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package au.org.ala.listsapi.model; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Data; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import lombok.experimental.SuperBuilder; | ||
|
||
@Getter | ||
@NoArgsConstructor | ||
@Data | ||
@SuperBuilder | ||
@AllArgsConstructor | ||
public class Location { | ||
private String isoCode; | ||
private String name; | ||
} |
115 changes: 115 additions & 0 deletions
115
lists-service/src/main/java/au/org/ala/listsapi/service/ValidationService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
package au.org.ala.listsapi.service; | ||
|
||
import au.org.ala.listsapi.model.*; | ||
import com.fasterxml.jackson.core.type.TypeReference; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import jakarta.annotation.PostConstruct; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.stereotype.Service; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.net.ProxySelector; | ||
import java.net.URI; | ||
import java.net.http.HttpClient; | ||
import java.net.http.HttpRequest; | ||
import java.net.http.HttpResponse; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
@Service | ||
public class ValidationService { | ||
|
||
public static final Logger log = LoggerFactory.getLogger(ValidationService.class); | ||
|
||
@Value("${constraints.file}") | ||
jack-brinkman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
private String constraintsFile; | ||
|
||
@Value("${userDetails.api.url}") | ||
jack-brinkman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
private String userDetailsUrl; | ||
|
||
private Map<String, List<ConstraintListItem>> constraints = null; | ||
|
||
private List<ConstraintListItem> getConstraintsByKey(ConstraintType constraintType) { | ||
return constraints.get(constraintType.name()); | ||
} | ||
|
||
private void setConstraintsByKey(ConstraintType constraintType, List<ConstraintListItem> items) { | ||
constraints.put(constraintType.name(), items); | ||
} | ||
|
||
@PostConstruct | ||
private void init() throws IOException { | ||
ObjectMapper objectMapper = new ObjectMapper(); | ||
File json = new File(constraintsFile); | ||
|
||
constraints = objectMapper.readValue(json, new TypeReference<HashMap<String, List<ConstraintListItem>>>() {}); | ||
|
||
try { | ||
List<Location> userdetailsCountries = fetchJson(userDetailsUrl + "/ws/registration/countries.json", new TypeReference<>() {}); | ||
List<ConstraintListItem> countries = getConstraintsByKey(ConstraintType.countries); | ||
|
||
// Map the countries list into UI constraints | ||
userdetailsCountries.forEach(e -> { | ||
var constraint = new ConstraintListItem(); | ||
constraint.setLabel(e.getName()); | ||
constraint.setValue(e.getIsoCode()); | ||
|
||
countries.add(constraint); | ||
}); | ||
|
||
setConstraintsByKey(ConstraintType.countries, countries); | ||
} catch (Exception ex) { | ||
log.error("Error loading country constraints from userdetails", ex); | ||
} | ||
} | ||
private <T> T fetchJson(String uri, TypeReference<T> type) throws Exception { | ||
HttpRequest httpRequest = | ||
HttpRequest.newBuilder(new URI(uri)) | ||
.GET() | ||
.build(); | ||
|
||
HttpResponse<String> response = | ||
HttpClient.newBuilder() | ||
.proxy(ProxySelector.getDefault()) | ||
.build() | ||
.send(httpRequest, HttpResponse.BodyHandlers.ofString()); | ||
|
||
ObjectMapper objectMapper = new ObjectMapper(); | ||
return objectMapper.readValue(response.body(), type); | ||
} | ||
|
||
// Returns the constraint list as a map of List<ConstraintListItem> to correctly output JSON | ||
public Map<String, List<ConstraintListItem>> getConstraintMap() { | ||
return constraints; | ||
} | ||
|
||
public boolean isValueValid(ConstraintType constraintType, String value) { | ||
List<ConstraintListItem> list = getConstraintsByKey(constraintType); | ||
|
||
return list.stream() | ||
.filter(elm -> elm.getValue().equals(value)) | ||
.findAny().orElse(null) != null; | ||
} | ||
|
||
public boolean isListValid(InputSpeciesList speciesList) { | ||
// check that the supplied list type, region and license is valid | ||
return ( | ||
isValueValid(ConstraintType.lists, speciesList.getListType()) && | ||
isValueValid(ConstraintType.licenses, speciesList.getLicence()) | ||
); | ||
} | ||
|
||
public List<ConstraintListItem> getConstraintList(ConstraintType constraintType) throws Exception { | ||
List<ConstraintListItem> list = getConstraintsByKey(constraintType); | ||
|
||
if (list == null) { | ||
throw new Exception("Could not find corresponding constraint list for '" + constraintType + "' type!"); | ||
} | ||
|
||
return list; | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The openapi annotations could be more detailed. I'll leave this as optional as the same can be said for the other services.