From 507ce46902b0e8f073cc7d2b37708f36ca2963bd Mon Sep 17 00:00:00 2001 From: Jiaqi Liu Date: Sat, 28 Sep 2024 22:03:59 +0800 Subject: [PATCH] Replace insecure native query endpoint with read-only language endpoint (#2) --- Dockerfile | 47 -------- Dockerfile-startup.sh | 20 ---- pom.xml | 81 ++++++-------- .../wilhelm}/application/BinderFactory.java | 2 +- .../wilhelm}/application/ResourceConfig.java | 6 +- .../wilhelm}/config/ApplicationConfig.java | 2 +- .../wilhelm}/web/endpoints/DataServlet.java | 67 ++++++------ .../wilhelm}/web/filters/CorsFilter.java | 2 +- .../web/endpoints/DataServletITSpec.groovy | 51 --------- .../wilhelm}/JettyServerFactorySpec.groovy | 5 +- .../application/ResourceConfigSpec.groovy | 4 +- .../web/endpoints/DataServletITSpec.groovy | 103 ++++++++++++++++++ .../web/endpoints/DataServletSpec.groovy | 2 +- .../web/filters/CorsFilterSpec.groovy | 2 +- .../qubitpi/wilhelm}/JettyServerFactory.java | 2 +- .../wilhelm}/resource/TestEndpoint.java | 7 +- ...wilhelm-ws-Project-intellij-code-style.xml | 6 +- 17 files changed, 193 insertions(+), 216 deletions(-) delete mode 100644 Dockerfile delete mode 100755 Dockerfile-startup.sh rename src/main/java/{com/qubitpi/ws/jersey/template => org/qubitpi/wilhelm}/application/BinderFactory.java (96%) rename src/main/java/{com/qubitpi/ws/jersey/template => org/qubitpi/wilhelm}/application/ResourceConfig.java (85%) rename src/main/java/{com/qubitpi/ws/jersey/template => org/qubitpi/wilhelm}/config/ApplicationConfig.java (98%) rename src/main/java/{com/qubitpi/ws/jersey/template => org/qubitpi/wilhelm}/web/endpoints/DataServlet.java (76%) rename src/main/java/{com/qubitpi/ws/jersey/template => org/qubitpi/wilhelm}/web/filters/CorsFilter.java (98%) delete mode 100644 src/test/groovy/com/qubitpi/ws/jersey/template/web/endpoints/DataServletITSpec.groovy rename src/test/groovy/{com/qubitpi/ws/jersey/template => org/qubitpi/wilhelm}/JettyServerFactorySpec.groovy (91%) rename src/test/groovy/{com/qubitpi/ws/jersey/template => org/qubitpi/wilhelm}/application/ResourceConfigSpec.groovy (92%) create mode 100644 src/test/groovy/org/qubitpi/wilhelm/web/endpoints/DataServletITSpec.groovy rename src/test/groovy/{com/qubitpi/ws/jersey/template => org/qubitpi/wilhelm}/web/endpoints/DataServletSpec.groovy (98%) rename src/test/groovy/{com/qubitpi/ws/jersey/template => org/qubitpi/wilhelm}/web/filters/CorsFilterSpec.groovy (99%) rename src/test/java/{com/qubitpi/ws/jersey/template => org/qubitpi/wilhelm}/JettyServerFactory.java (98%) rename src/test/java/{com/qubitpi/ws/jersey/template => org/qubitpi/wilhelm}/resource/TestEndpoint.java (82%) rename aristotle-Project-intellij-code-style.xml => wilhelm-ws-Project-intellij-code-style.xml (96%) diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index a204829..0000000 --- a/Dockerfile +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright Jiaqi Liu -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -FROM ubuntu:22.04 - -LABEL maintainer="Jiaqi (Jack) Liu" -LABEL maintainer-email="jack20220723@gmail.com" - -ARG WS_VERSION=1.0-SNAPSHOT - -ENV JAVA_HOME /usr/lib/jvm/java-17-openjdk-amd64 - -ENV JETTY_VERSION 11.0.15 -ENV JETTY_BASE /jetty-base -ENV JETTY_HOME /jetty-home-$JETTY_VERSION -ENV JETTY_WEBAPPS_DIR $JETTY_BASE/webapps - -RUN apt update -RUN apt upgrade -y -RUN apt install software-properties-common -y -RUN apt install wget - -# Install JDK 17 - https://www.rosehosting.com/blog/how-to-install-java-17-lts-on-ubuntu-20-04/ -RUN apt update -y -RUN apt install openjdk-17-jdk -y - -# Install and configure Jetty (for JDK 17) container -RUN wget https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-home/$JETTY_VERSION/jetty-home-$JETTY_VERSION.tar.gz -RUN tar -xzvf jetty-home-$JETTY_VERSION.tar.gz -RUN rm jetty-home-$JETTY_VERSION.tar.gz -RUN mkdir jetty-base -RUN cd jetty-base && java -jar $JETTY_HOME/start.jar --add-module=annotations,server,http,deploy,servlet,webapp,resources,jsp - -COPY ./target/jersey-webservice-template-$WS_VERSION.war $JETTY_WEBAPPS_DIR/ROOT.war - -COPY ./Dockerfile-startup.sh /Dockerfile-startup.sh -CMD [ "/Dockerfile-startup.sh" ] diff --git a/Dockerfile-startup.sh b/Dockerfile-startup.sh deleted file mode 100755 index 97aa9b5..0000000 --- a/Dockerfile-startup.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash -set -x -set -e - -# Copyright Jiaqi Liu -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -cd $JETTY_BASE -java -jar $JETTY_HOME/start.jar diff --git a/pom.xml b/pom.xml index a428d91..cce952c 100644 --- a/pom.xml +++ b/pom.xml @@ -4,14 +4,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.qubitpi - jersey-webservice-template + org.qubitpi.wilhelm + wilhelm-ws 1.0-SNAPSHOT war - Jersey Webservice Template - Template project for building Jersey webservice running in Jetty - https://github.com/QubitPi/jersey-webservice-template + Wilhelm Webservice + Serving data from graph database for wilhelmlang.com + https://github.com/QubitPi/wilhelm-ws @@ -29,34 +29,13 @@ - UTF-8 17 17 + UTF-8 - 3.0.1 - 1.0 - 1.7.25 - 1.2.3 - 2.13.3 - 1.0.12 - 6.0.0 3.1.1 - 4.0.6 - 11.0.15 - - 3.2.2 - 3.5.0 - 3.1.1 - 3.0.0-M5 - 3.7.0 - 3.0.0-M4 - 3.1.2 - ${version.maven.surefire.plugin} false - checkstyle.xml - checkstyle-suppressions.xml - 8.30 **/*.properties* @@ -66,7 +45,7 @@ com.fasterxml.jackson jackson-bom - ${version.jackson} + 2.13.3 import pom @@ -82,7 +61,7 @@ org.eclipse.jetty jetty-bom - ${version.jetty} + 11.0.15 pom import @@ -105,14 +84,14 @@ jakarta.validation jakarta.validation-api - ${version.validation.api} + 3.0.1 jakarta.servlet jakarta.servlet-api - ${version.servlet} + 6.0.0 jakarta.ws.rs @@ -182,26 +161,26 @@ net.jcip jcip-annotations - ${version.jcip.annotations} + 1.0 org.aeonbits.owner owner - ${version.owner} + 1.0.12 org.slf4j slf4j-api - ${version.slf4j} + 1.7.25 ch.qos.logback logback-classic - ${version.logback} + 1.2.3 net.logstash.logback @@ -223,7 +202,7 @@ org.apache.groovy groovy - ${version.groovy} + 4.0.6 test @@ -268,6 +247,13 @@ + + + org.testcontainers + spock + 1.20.1 + test + @@ -282,7 +268,7 @@ org.apache.maven.plugins maven-compiler-plugin - ${version.maven.compiler.plugin} + 3.7.0 ${maven.compiler.source} ${maven.compiler.target} @@ -294,19 +280,20 @@ org.apache.maven.plugins maven-checkstyle-plugin - ${version.maven.checkstyle.plugin} + 3.1.2 com.puppycrawl.tools checkstyle - ${checkstyle.version} + 8.30 - ${checkstyle.suppressions.location} + checkstyle-suppressions.xml checkstyle.suppressions.file - ${checkstyle.config.location} + checkstyle.xml + checkstyle.xml **\/*.java,**\/*.groovy **/*.properties,**/*.sample true @@ -326,7 +313,7 @@ org.apache.maven.plugins maven-javadoc-plugin - ${version.maven.javadoc.plugin} + 3.5.0 none @@ -360,7 +347,7 @@ org.apache.maven.plugins maven-surefire-plugin - ${version.maven.surefire.plugin} + 3.0.0-M5 true @@ -376,14 +363,14 @@ org.apache.maven.plugins maven-surefire-report-plugin - ${version.maven.surefire.report.plugin} + 3.0.0-M5 org.apache.maven.plugins maven-failsafe-plugin - ${version.maven.failsafe.plugin} + 3.0.0-M4 @@ -402,7 +389,7 @@ org.apache.maven.plugins maven-war-plugin - ${version.maven.war.plugin} + 3.2.2 false @@ -411,7 +398,7 @@ org.apache.maven.plugins maven-jar-plugin - ${version.maven.jar.plugin} + 3.1.1 diff --git a/src/main/java/com/qubitpi/ws/jersey/template/application/BinderFactory.java b/src/main/java/org/qubitpi/wilhelm/application/BinderFactory.java similarity index 96% rename from src/main/java/com/qubitpi/ws/jersey/template/application/BinderFactory.java rename to src/main/java/org/qubitpi/wilhelm/application/BinderFactory.java index d80c112..57c5ed7 100644 --- a/src/main/java/com/qubitpi/ws/jersey/template/application/BinderFactory.java +++ b/src/main/java/org/qubitpi/wilhelm/application/BinderFactory.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.qubitpi.ws.jersey.template.application; +package org.qubitpi.wilhelm.application; import org.glassfish.hk2.utilities.Binder; import org.glassfish.hk2.utilities.binding.AbstractBinder; diff --git a/src/main/java/com/qubitpi/ws/jersey/template/application/ResourceConfig.java b/src/main/java/org/qubitpi/wilhelm/application/ResourceConfig.java similarity index 85% rename from src/main/java/com/qubitpi/ws/jersey/template/application/ResourceConfig.java rename to src/main/java/org/qubitpi/wilhelm/application/ResourceConfig.java index 4d23727..bc148a5 100644 --- a/src/main/java/com/qubitpi/ws/jersey/template/application/ResourceConfig.java +++ b/src/main/java/org/qubitpi/wilhelm/application/ResourceConfig.java @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.qubitpi.ws.jersey.template.application; +package org.qubitpi.wilhelm.application; -import com.qubitpi.ws.jersey.template.web.filters.CorsFilter; +import org.qubitpi.wilhelm.web.filters.CorsFilter; import org.glassfish.hk2.utilities.Binder; @@ -32,7 +32,7 @@ @ApplicationPath("v1") public class ResourceConfig extends org.glassfish.jersey.server.ResourceConfig { - private static final String ENDPOINT_PACKAGE = "com.qubitpi.ws.jersey.template.web.endpoints"; + private static final String ENDPOINT_PACKAGE = "org.qubitpi.wilhelm.web.endpoints"; /** * DI Constructor that allows for finer dependency injection control. diff --git a/src/main/java/com/qubitpi/ws/jersey/template/config/ApplicationConfig.java b/src/main/java/org/qubitpi/wilhelm/config/ApplicationConfig.java similarity index 98% rename from src/main/java/com/qubitpi/ws/jersey/template/config/ApplicationConfig.java rename to src/main/java/org/qubitpi/wilhelm/config/ApplicationConfig.java index 2379785..f7428f7 100644 --- a/src/main/java/com/qubitpi/ws/jersey/template/config/ApplicationConfig.java +++ b/src/main/java/org/qubitpi/wilhelm/config/ApplicationConfig.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.qubitpi.ws.jersey.template.config; +package org.qubitpi.wilhelm.config; import org.aeonbits.owner.Config; diff --git a/src/main/java/com/qubitpi/ws/jersey/template/web/endpoints/DataServlet.java b/src/main/java/org/qubitpi/wilhelm/web/endpoints/DataServlet.java similarity index 76% rename from src/main/java/com/qubitpi/ws/jersey/template/web/endpoints/DataServlet.java rename to src/main/java/org/qubitpi/wilhelm/web/endpoints/DataServlet.java index 44dc0af..f962819 100644 --- a/src/main/java/com/qubitpi/ws/jersey/template/web/endpoints/DataServlet.java +++ b/src/main/java/org/qubitpi/wilhelm/web/endpoints/DataServlet.java @@ -13,12 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.qubitpi.ws.jersey.template.web.endpoints; +package org.qubitpi.wilhelm.web.endpoints; -import com.qubitpi.ws.jersey.template.config.ApplicationConfig; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; +import org.qubitpi.wilhelm.config.ApplicationConfig; import org.aeonbits.owner.ConfigFactory; import org.neo4j.driver.AuthTokens; @@ -33,8 +30,8 @@ import jakarta.inject.Singleton; import jakarta.validation.constraints.NotNull; import jakarta.ws.rs.GET; -import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; @@ -43,7 +40,9 @@ import java.util.AbstractMap; import java.util.Map; +import java.util.Objects; import java.util.stream.Collectors; +import java.util.stream.Stream; import java.util.stream.StreamSupport; /** @@ -62,7 +61,12 @@ public class DataServlet { private static final String NEO4J_PASSWORD = APPLICATION_CONFIG.neo4jPassword(); private static final String NEO4J_DATABASE = APPLICATION_CONFIG.neo4jDatabase(); - private static final ObjectMapper JSON_MAPPER = new ObjectMapper(); + private static final Map LANGUAGES = Stream.of( + new AbstractMap.SimpleImmutableEntry<>("german", "German"), + new AbstractMap.SimpleImmutableEntry<>("ancientGreek", "Ancient Greek"), + new AbstractMap.SimpleImmutableEntry<>("latin", "Latin") + ) + .collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, Map.Entry::getValue)); /** @@ -87,33 +91,34 @@ public Response healthcheck() { } /** - * Sends a native Neo4J query. - * - * @param body A JSON body of the form - *
-     * {@code
-     * {
-     *     "query": ""
-     * }
-     * }
-     * 
- * For example - *
-     * {@code
-     * {
-     *     "query": "MATCH (term:Term)-[:DEFINITION]->(definition:Definition) RETURN term, definition;"
-     * }
-     * }
-     * 
+ * Get all vocabularies of a language. * - * @return The native query response serialized into JSON + * @param language The language. Must be one of "german", "ancientGreek", or "latin". Otherwise a 404 response is + * returned * - * @throws JsonProcessingException if the {@code body} payload is an invalid JSON + * @return the Neo4J query results in JSON format */ - @POST - @Path("/query") - public Response query(@NotNull final String body) throws JsonProcessingException { - final String query = JSON_MAPPER.readTree(body).get("query").asText(); + @GET + @Path("/languages/{language}") + @Produces(MediaType.APPLICATION_JSON) + public Response getVocabularyByLanguage(@NotNull @PathParam("language") final String language) { + if (!LANGUAGES.containsKey(Objects.requireNonNull(language, "language"))) { + return Response + .status(Response.Status.BAD_REQUEST) + .entity( + String.format( + "'language' path parameter has to be one of %s", + String.join(", ", LANGUAGES.keySet()) + ) + ) + .build(); + } + + final String query = String.format( + "MATCH (t:Term WHERE t.language = '%s')-[r]->(d:Definition) " + + "RETURN t.name AS term, d.name AS definition", + LANGUAGES.get(language) + ); try (Driver driver = GraphDatabase.driver(NEO4J_URL, AuthTokens.basic(NEO4J_USERNAME, NEO4J_PASSWORD))) { driver.verifyConnectivity(); diff --git a/src/main/java/com/qubitpi/ws/jersey/template/web/filters/CorsFilter.java b/src/main/java/org/qubitpi/wilhelm/web/filters/CorsFilter.java similarity index 98% rename from src/main/java/com/qubitpi/ws/jersey/template/web/filters/CorsFilter.java rename to src/main/java/org/qubitpi/wilhelm/web/filters/CorsFilter.java index 4784c18..1b37535 100644 --- a/src/main/java/com/qubitpi/ws/jersey/template/web/filters/CorsFilter.java +++ b/src/main/java/org/qubitpi/wilhelm/web/filters/CorsFilter.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.qubitpi.ws.jersey.template.web.filters; +package org.qubitpi.wilhelm.web.filters; import jakarta.annotation.Priority; import jakarta.validation.constraints.NotNull; diff --git a/src/test/groovy/com/qubitpi/ws/jersey/template/web/endpoints/DataServletITSpec.groovy b/src/test/groovy/com/qubitpi/ws/jersey/template/web/endpoints/DataServletITSpec.groovy deleted file mode 100644 index a356269..0000000 --- a/src/test/groovy/com/qubitpi/ws/jersey/template/web/endpoints/DataServletITSpec.groovy +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright Jiaqi Liu - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.qubitpi.ws.jersey.template.web.endpoints - -import com.qubitpi.ws.jersey.template.JettyServerFactory -import com.qubitpi.ws.jersey.template.application.ResourceConfig - -import org.eclipse.jetty.server.Server - -import io.restassured.RestAssured -import spock.lang.Specification - -class DataServletITSpec extends Specification { - - static final int PORT = 8080 - - def setupSpec() { - RestAssured.baseURI = "http://localhost" - RestAssured.port = PORT - RestAssured.basePath = "/v1" - } - - def "Healthchecking endpoints returns 200"() { - setup: - Server server = JettyServerFactory.newInstance(PORT, "/v1/*", new ResourceConfig()) - server.start() - - expect: - RestAssured.given() - .when() - .get("/data/healthcheck") - .then() - .statusCode(200) - - cleanup: - server.stop() - } -} diff --git a/src/test/groovy/com/qubitpi/ws/jersey/template/JettyServerFactorySpec.groovy b/src/test/groovy/org/qubitpi/wilhelm/JettyServerFactorySpec.groovy similarity index 91% rename from src/test/groovy/com/qubitpi/ws/jersey/template/JettyServerFactorySpec.groovy rename to src/test/groovy/org/qubitpi/wilhelm/JettyServerFactorySpec.groovy index 07d9e2e..751471b 100755 --- a/src/test/groovy/com/qubitpi/ws/jersey/template/JettyServerFactorySpec.groovy +++ b/src/test/groovy/org/qubitpi/wilhelm/JettyServerFactorySpec.groovy @@ -13,13 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.qubitpi.ws.jersey.template +package org.qubitpi.wilhelm import org.eclipse.jetty.server.Server import org.glassfish.jersey.server.ResourceConfig import io.restassured.RestAssured -import io.restassured.builder.RequestSpecBuilder import jakarta.inject.Inject import jakarta.ws.rs.ApplicationPath import spock.lang.Specification @@ -27,7 +26,7 @@ import spock.lang.Specification class JettyServerFactorySpec extends Specification { static final int PORT = 8080 - static final String ENDPOINT_RESOURCE_PACKAGE = "com.qubitpi.ws.jersey.template.resource" + static final String ENDPOINT_RESOURCE_PACKAGE = "org.qubitpi.wilhelm.resource" /** * DI constructor. diff --git a/src/test/groovy/com/qubitpi/ws/jersey/template/application/ResourceConfigSpec.groovy b/src/test/groovy/org/qubitpi/wilhelm/application/ResourceConfigSpec.groovy similarity index 92% rename from src/test/groovy/com/qubitpi/ws/jersey/template/application/ResourceConfigSpec.groovy rename to src/test/groovy/org/qubitpi/wilhelm/application/ResourceConfigSpec.groovy index 861c8b1..e51961f 100644 --- a/src/test/groovy/com/qubitpi/ws/jersey/template/application/ResourceConfigSpec.groovy +++ b/src/test/groovy/org/qubitpi/wilhelm/application/ResourceConfigSpec.groovy @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.qubitpi.ws.jersey.template.application +package org.qubitpi.wilhelm.application -import com.qubitpi.ws.jersey.template.web.filters.CorsFilter import org.glassfish.jersey.internal.inject.Binder +import org.qubitpi.wilhelm.web.filters.CorsFilter import spock.lang.Specification diff --git a/src/test/groovy/org/qubitpi/wilhelm/web/endpoints/DataServletITSpec.groovy b/src/test/groovy/org/qubitpi/wilhelm/web/endpoints/DataServletITSpec.groovy new file mode 100644 index 0000000..503ee08 --- /dev/null +++ b/src/test/groovy/org/qubitpi/wilhelm/web/endpoints/DataServletITSpec.groovy @@ -0,0 +1,103 @@ +/* + * Copyright Jiaqi Liu + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.qubitpi.wilhelm.web.endpoints + +import static org.hamcrest.Matchers.equalTo + +import org.hamcrest.Description +import org.hamcrest.Matcher +import org.hamcrest.Matchers +import org.hamcrest.TypeSafeMatcher +import org.qubitpi.wilhelm.JettyServerFactory +import org.qubitpi.wilhelm.application.ResourceConfig + +import org.eclipse.jetty.server.Server +import org.testcontainers.containers.GenericContainer +import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy +import org.testcontainers.spock.Testcontainers + +import groovy.json.JsonBuilder +import io.restassured.RestAssured +import io.restassured.http.ContentType +import jakarta.ws.rs.core.MediaType +import spock.lang.Shared +import spock.lang.Specification + +import java.time.Duration +import java.time.temporal.ChronoUnit + +@Testcontainers +class DataServletITSpec extends Specification { + + static final int PORT = 8080 + + @Shared + static final GenericContainer NEO4J_CONTAINER = new GenericContainer<>("jack20191124/wilhelm-vocabulary") + .withExposedPorts(7474, 7687) + .withEnv([ + NEO4J_AUTH: "none", + NEO4J_ACCEPT_LICENSE_AGREEMENT: "yes" + ]) + .waitingFor(new LogMessageWaitStrategy().withRegEx(".*INFO Started.*")) + .withStartupTimeout(Duration.of(60, ChronoUnit.SECONDS)) + + Server server = JettyServerFactory.newInstance(PORT, "/v1/*", new ResourceConfig()) + + def setupSpec() { + RestAssured.baseURI = "http://localhost" + RestAssured.port = PORT + RestAssured.basePath = "/v1" + + NEO4J_CONTAINER.start() + + System.setProperty("NEO4J_URI", String.format("neo4j://localhost:%d", NEO4J_CONTAINER.getMappedPort(7687))) + System.setProperty("NEO4J_USERNAME", "NOT USED") + System.setProperty("NEO4J_PASSWORD", "NOT USED") + System.setProperty("NEO4J_DATABASE", "neo4j") + + // We need to figure out how to fill DB with some initial data. Coming back to this ASAP + } + + def setup() { + server.start() + } + + def cleanup() { + server.stop() + } + + def "Healthchecking endpoints returns 200"() { + expect: + RestAssured.given() + .when() + .get("/data/healthcheck") + .then() + .statusCode(200) + } + + def "Get vocabulary by language"() { + expect: + RestAssured + .given() + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .when() + .get("/data/languages/german") + .then() + .statusCode(200) + .body("[0]", equalTo([term: "dieser", definition: "this"])) + } +} diff --git a/src/test/groovy/com/qubitpi/ws/jersey/template/web/endpoints/DataServletSpec.groovy b/src/test/groovy/org/qubitpi/wilhelm/web/endpoints/DataServletSpec.groovy similarity index 98% rename from src/test/groovy/com/qubitpi/ws/jersey/template/web/endpoints/DataServletSpec.groovy rename to src/test/groovy/org/qubitpi/wilhelm/web/endpoints/DataServletSpec.groovy index 987a0df..7d29293 100644 --- a/src/test/groovy/com/qubitpi/ws/jersey/template/web/endpoints/DataServletSpec.groovy +++ b/src/test/groovy/org/qubitpi/wilhelm/web/endpoints/DataServletSpec.groovy @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.qubitpi.ws.jersey.template.web.endpoints +package org.qubitpi.wilhelm.web.endpoints import org.neo4j.driver.Value diff --git a/src/test/groovy/com/qubitpi/ws/jersey/template/web/filters/CorsFilterSpec.groovy b/src/test/groovy/org/qubitpi/wilhelm/web/filters/CorsFilterSpec.groovy similarity index 99% rename from src/test/groovy/com/qubitpi/ws/jersey/template/web/filters/CorsFilterSpec.groovy rename to src/test/groovy/org/qubitpi/wilhelm/web/filters/CorsFilterSpec.groovy index ad1f232..4feca6d 100644 --- a/src/test/groovy/com/qubitpi/ws/jersey/template/web/filters/CorsFilterSpec.groovy +++ b/src/test/groovy/org/qubitpi/wilhelm/web/filters/CorsFilterSpec.groovy @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.qubitpi.ws.jersey.template.web.filters +package org.qubitpi.wilhelm.web.filters import jakarta.ws.rs.container.ContainerRequestContext import jakarta.ws.rs.container.ContainerResponseContext diff --git a/src/test/java/com/qubitpi/ws/jersey/template/JettyServerFactory.java b/src/test/java/org/qubitpi/wilhelm/JettyServerFactory.java similarity index 98% rename from src/test/java/com/qubitpi/ws/jersey/template/JettyServerFactory.java rename to src/test/java/org/qubitpi/wilhelm/JettyServerFactory.java index c970727..991cd27 100755 --- a/src/test/java/com/qubitpi/ws/jersey/template/JettyServerFactory.java +++ b/src/test/java/org/qubitpi/wilhelm/JettyServerFactory.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.qubitpi.ws.jersey.template; +package org.qubitpi.wilhelm; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; diff --git a/src/test/java/com/qubitpi/ws/jersey/template/resource/TestEndpoint.java b/src/test/java/org/qubitpi/wilhelm/resource/TestEndpoint.java similarity index 82% rename from src/test/java/com/qubitpi/ws/jersey/template/resource/TestEndpoint.java rename to src/test/java/org/qubitpi/wilhelm/resource/TestEndpoint.java index 86d8bf7..220c93e 100755 --- a/src/test/java/com/qubitpi/ws/jersey/template/resource/TestEndpoint.java +++ b/src/test/java/org/qubitpi/wilhelm/resource/TestEndpoint.java @@ -13,9 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.qubitpi.ws.jersey.template.resource; +package org.qubitpi.wilhelm.resource; import org.glassfish.jersey.server.ResourceConfig; +import org.qubitpi.wilhelm.JettyServerFactory; import jakarta.inject.Singleton; import jakarta.ws.rs.GET; @@ -25,9 +26,9 @@ import net.jcip.annotations.ThreadSafe; /** - * A JAX-RS resource class used for testing {@link com.qubitpi.ws.jersey.template.JettyServerFactory}. + * A JAX-RS resource class used for testing {@link JettyServerFactory}. * - * see {@link com.qubitpi.ws.jersey.template.JettyServerFactory#newInstance(int, String, ResourceConfig)} for why we + * see {@link JettyServerFactory#newInstance(int, String, ResourceConfig)} for why we * need to prefix @Path with "/v1" */ @Singleton diff --git a/aristotle-Project-intellij-code-style.xml b/wilhelm-ws-Project-intellij-code-style.xml similarity index 96% rename from aristotle-Project-intellij-code-style.xml rename to wilhelm-ws-Project-intellij-code-style.xml index 17e522f..1d9b763 100644 --- a/aristotle-Project-intellij-code-style.xml +++ b/wilhelm-ws-Project-intellij-code-style.xml @@ -1,4 +1,4 @@ - +