diff --git a/backend/build.gradle b/backend/build.gradle index a204e0ea1..6fae24ee8 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -14,6 +14,7 @@ targetCompatibility = 1.8 repositories { maven { url 'https://build.shibboleth.net/nexus/content/groups/public' } mavenCentral() + jcenter() } processResources.dependsOn(':ui:npm_run_buildProd') @@ -61,6 +62,9 @@ dependencies { compile "org.liquibase:liquibase-core" compile group: 'org.jadira.usertype', name: 'usertype.core', version: '6.0.1.GA' + //For easy data mocking capabilities + compile 'net.andreinc.mockneat:mockneat:0.1.4' + //So it works on Java 9 without explicitly requiring to load that module (needed by Hibernate) runtimeOnly 'javax.xml.bind:jaxb-api:2.3.0' @@ -76,7 +80,7 @@ dependencies { testRuntime 'cglib:cglib-nodep:3.2.5' //JSON schema generator - testCompile 'com.kjetland:mbknor-jackson-jsonschema_2.12:1.0.28' + testCompile 'com.kjetland:mbknor-jackson-jsonschema_2.12:1.0.29' testCompile 'javax.validation:validation-api:2.0.1.Final' } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/CoreShibUiConfiguration.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/CoreShibUiConfiguration.java index 228a27cf8..34085e489 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/CoreShibUiConfiguration.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/CoreShibUiConfiguration.java @@ -1,14 +1,19 @@ package edu.internet2.tier.shibboleth.admin.ui.configuration; +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityIdsSearchResultRepresentation; import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects; import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository; import edu.internet2.tier.shibboleth.admin.ui.scheduled.EntityDescriptorFilesScheduledTasks; import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService; +import edu.internet2.tier.shibboleth.admin.ui.service.EntityIdsSearchService; import edu.internet2.tier.shibboleth.admin.ui.service.JPAEntityDescriptorServiceImpl; +import net.andreinc.mockneat.MockNeat; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import java.util.List; + @Configuration public class CoreShibUiConfiguration { @@ -30,4 +35,15 @@ public EntityDescriptorService jpaEntityDescriptorService() { public EntityDescriptorFilesScheduledTasks entityDescriptorFilesScheduledTasks(EntityDescriptorRepository entityDescriptorRepository) { return new EntityDescriptorFilesScheduledTasks(this.metadataDir, entityDescriptorRepository, openSamlObjects()); } + + @Bean + public EntityIdsSearchService entityIdsSearchService() { + //TODO: replace with real data store implementation when ready + return (term, limit) -> { + MockNeat m = MockNeat.threadLocal(); + // Just simulate returning 100 results for no-limit query + List simulatedEntityIds = limit > 0 ? m.urls().list(limit).val() : m.urls().list(100).val(); + return new EntityIdsSearchResultRepresentation(simulatedEntityIds); + }; + } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityIdsSearchController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityIdsSearchController.java new file mode 100644 index 000000000..f2df32b98 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityIdsSearchController.java @@ -0,0 +1,27 @@ +package edu.internet2.tier.shibboleth.admin.ui.controller; + +import edu.internet2.tier.shibboleth.admin.ui.service.EntityIdsSearchService; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + + +@RestController +@RequestMapping("/api/EntityIds/search") +public class EntityIdsSearchController { + + EntityIdsSearchService entityIdsSearchService; + + public EntityIdsSearchController(EntityIdsSearchService entityIdsSearchService) { + this.entityIdsSearchService = entityIdsSearchService; + } + + @GetMapping + ResponseEntity search(@RequestParam String term, @RequestParam(required = false) Integer limit) { + //Zero indicates no-limit + final int resultLimit = (limit != null ? limit : 0); + return ResponseEntity.ok(this.entityIdsSearchService.findBySearchTermAndOptionalLimit(term, resultLimit)); + } +} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/frontend/EntityIdsSearchResultRepresentation.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/frontend/EntityIdsSearchResultRepresentation.java new file mode 100644 index 000000000..db741a597 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/frontend/EntityIdsSearchResultRepresentation.java @@ -0,0 +1,21 @@ +package edu.internet2.tier.shibboleth.admin.ui.domain.frontend; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class EntityIdsSearchResultRepresentation implements Serializable { + + private static final long serialVersionUID = 8150816733364873026L; + + private List entityIds = new ArrayList<>(); + + public EntityIdsSearchResultRepresentation(List entityIds) { + this.entityIds = entityIds; + } + + public List getEntityIds() { + return Collections.unmodifiableList(entityIds); + } +} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityIdsSearchService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityIdsSearchService.java new file mode 100644 index 000000000..81b8a4b1c --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityIdsSearchService.java @@ -0,0 +1,23 @@ +package edu.internet2.tier.shibboleth.admin.ui.service; + +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityIdsSearchResultRepresentation; +import net.andreinc.mockneat.MockNeat; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +/** + * API component responsible for entity ids search. + */ +@FunctionalInterface +public interface EntityIdsSearchService { + + /** + * Find a list of entity ids + * @param searchTerm for the query + * @param limit optional limit of query results to return. Zero or less value indicates no limit. + * @return EntityIdsSearchResultRepresentation + */ + EntityIdsSearchResultRepresentation findBySearchTermAndOptionalLimit(String searchTerm, int limit); +} diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/restapi/JsonSchemaGeneration.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/restapi/JsonSchemaGeneration.groovy deleted file mode 100644 index 01729e7df..000000000 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/restapi/JsonSchemaGeneration.groovy +++ /dev/null @@ -1,24 +0,0 @@ -package edu.internet2.tier.shibboleth.admin.ui.restapi - -import com.fasterxml.jackson.databind.ObjectMapper -import com.kjetland.jackson.jsonSchema.JsonSchemaGenerator -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation - -import spock.lang.Specification - -import static com.fasterxml.jackson.databind.SerializationFeature.INDENT_OUTPUT - -class JsonSchemaGeneration extends Specification { - - /*def setupSpec() { - def om = new ObjectMapper().with {it.enable(INDENT_OUTPUT); it} - def schemaGenerator = new JsonSchemaGenerator(om) - def jsonSchema = schemaGenerator.generateJsonSchema(EntityDescriptorRepresentation) - - def jsonSchemaOutputFile = new File('src/test/resources/entity-descriptor-json-schema.json') - jsonSchemaOutputFile.delete() - jsonSchemaOutputFile.withWriter('UTF-8') { - it.write(jsonSchema.toString()) - } - }*/ -} \ No newline at end of file diff --git a/backend/src/test/resources/entity-ids-search-json-schema.json b/backend/src/test/resources/entity-ids-search-json-schema.json new file mode 100644 index 000000000..6c67c56af --- /dev/null +++ b/backend/src/test/resources/entity-ids-search-json-schema.json @@ -0,0 +1,14 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Entity Ids Search Result Representation", + "type": "object", + "additionalProperties": false, + "properties": { + "entityIds": { + "type": "array", + "items": { + "type": "string" + } + } + } +} \ No newline at end of file diff --git a/backend/src/test/scripts/generate-json-schema.groovy b/backend/src/test/scripts/generate-json-schema.groovy new file mode 100644 index 000000000..10086eddd --- /dev/null +++ b/backend/src/test/scripts/generate-json-schema.groovy @@ -0,0 +1,22 @@ +import com.fasterxml.jackson.databind.ObjectMapper +import com.kjetland.jackson.jsonSchema.JsonSchemaGenerator +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityIdsSearchResultRepresentation + +import static com.fasterxml.jackson.databind.SerializationFeature.INDENT_OUTPUT + +TARGET_DIRECTORY = "../resources" + +def generateSchemaFor(Class clazz, String outputFileName) { + def om = new ObjectMapper().with { it.enable(INDENT_OUTPUT); it } + def schemaGenerator = new JsonSchemaGenerator(om) + def jsonSchema = schemaGenerator.generateJsonSchema(clazz) + + def jsonSchemaOutputFile = new File("$TARGET_DIRECTORY/$outputFileName") + jsonSchemaOutputFile.delete() + jsonSchemaOutputFile.withWriter('UTF-8') { + it.write(jsonSchema.toString()) + } +} + +generateSchemaFor(EntityIdsSearchResultRepresentation, "entity-ids-search-json-schema.json") \ No newline at end of file