-
Notifications
You must be signed in to change notification settings - Fork 0
Features/thymeleaf module #60
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| .git/ | ||
| .gitattributes | ||
| .gitignore | ||
| .github/ | ||
|
|
||
| .idea/ | ||
| .vscode/ | ||
| *.iml | ||
| *.ipr | ||
| *.iws | ||
| *.sw? | ||
| *.orig | ||
|
|
||
| .DS_Store | ||
| Thumbs.db | ||
|
|
||
| **/target/ | ||
|
|
||
| !.mvn/ | ||
| !mvnw | ||
| !mvnw.cmd |
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,76 @@ | ||||||||||||||
| # syntax=docker/dockerfile:1.6 | ||||||||||||||
| FROM eclipse-temurin:21 AS deps | ||||||||||||||
| WORKDIR /code | ||||||||||||||
| ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 | ||||||||||||||
|
|
||||||||||||||
| # Copy only Maven wrapper + .mvn + every pom.xml from the build context, | ||||||||||||||
| # without enumerating modules (requires BuildKit). | ||||||||||||||
| RUN --mount=type=bind,source=.,target=/src,ro \ | ||||||||||||||
| bash -ceu ' \ | ||||||||||||||
| mkdir -p /code; \ | ||||||||||||||
| cd /src; \ | ||||||||||||||
| # copy Maven wrapper if present | ||||||||||||||
| cp mvnw /code/; \ | ||||||||||||||
| mkdir -p /code/.mvn && cp -R .mvn/. /code/.mvn/; \ | ||||||||||||||
| # copy all pom.xml preserving directory structure | ||||||||||||||
| while IFS= read -r -d "" p; do \ | ||||||||||||||
| mkdir -p /code/"$(dirname "$p")"; \ | ||||||||||||||
| cp "$p" /code/"$p"; \ | ||||||||||||||
| done < <(find . -name pom.xml -type f -print0); \ | ||||||||||||||
| ' | ||||||||||||||
|
|
||||||||||||||
| RUN --mount=type=cache,target=/root/.m2 \ | ||||||||||||||
| ./mvnw -B -DskipTests \ | ||||||||||||||
| -DoutputAbsoluteArtifactFilename=true \ | ||||||||||||||
| -DincludePlugins=true \ | ||||||||||||||
| org.apache.maven.plugins:maven-dependency-plugin:3.8.1:go-offline | ||||||||||||||
|
|
||||||||||||||
| FROM eclipse-temurin:21 AS builder | ||||||||||||||
| WORKDIR /code | ||||||||||||||
| ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 | ||||||||||||||
|
|
||||||||||||||
| ARG DB_HOST | ||||||||||||||
| ARG DB_PORT | ||||||||||||||
| ARG DB_DATABASE | ||||||||||||||
| ARG DB_USER | ||||||||||||||
| ARG DB_PASSWORD | ||||||||||||||
|
|
||||||||||||||
|
Comment on lines
+32
to
+37
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion DB credentials as build args leak into image history. Build-time args are visible in layer history and logs; don’t pass secrets this way. Use BuildKit secrets for the password and minimal-privilege codegen user: -ARG DB_PASSWORD
+ARG DB_PASSWORD # kept for local dev, prefer secret in CIAnd in the build step: -RUN --mount=type=cache,target=/root/.m2 \
+RUN --mount=type=cache,target=/root/.m2 \
+ --mount=type=secret,id=dbpass \
dockerize -wait tcp://${DB_HOST}:${DB_PORT} -timeout 60s \
&& ./mvnw clean package \
@@
- -Ddb.password="${DB_PASSWORD}" \
+ -Ddb.password="$(cat /run/secrets/dbpass || echo ${DB_PASSWORD})" \Document building with: docker build --secret id=dbpass,src=./db.pass … |
||||||||||||||
| COPY . /code | ||||||||||||||
|
|
||||||||||||||
| # Download and install dockerize. | ||||||||||||||
| # Needed so the web container will wait for MariaDB to start. | ||||||||||||||
| # Wait for the db to startup(via dockerize), then | ||||||||||||||
| # Build steve, requires a db to be available on port 3306 | ||||||||||||||
| ARG PORT=8180 | ||||||||||||||
| ARG DOCKERIZE_VERSION=v0.19.0 | ||||||||||||||
| RUN curl -sfL "https://github.com/powerman/dockerize/releases/download/${DOCKERIZE_VERSION}/dockerize-$(uname -s)-$(uname -m)" \ | ||||||||||||||
| | install /dev/stdin /usr/local/bin/dockerize | ||||||||||||||
|
|
||||||||||||||
| RUN --mount=type=cache,target=/root/.m2 \ | ||||||||||||||
| dockerize -wait tcp://${DB_HOST}:${DB_PORT} -timeout 60s \ | ||||||||||||||
| && ./mvnw clean package \ | ||||||||||||||
| -DskipTests \ | ||||||||||||||
| -Dhttp.port=${PORT} \ | ||||||||||||||
| -Dserver.host="0.0.0.0" \ | ||||||||||||||
| -Ddb.ip="${DB_HOST}" \ | ||||||||||||||
| -Ddb.port=${DB_PORT} \ | ||||||||||||||
| -Ddb.schema="${DB_DATABASE}" \ | ||||||||||||||
| -Ddb.user="${DB_USER}" \ | ||||||||||||||
| -Ddb.password="${DB_PASSWORD}" \ | ||||||||||||||
| -Dserver.gzip.enabled=false \ | ||||||||||||||
| -Dappender="CONSOLE" \ | ||||||||||||||
| -Djdk.tls.client.protocols="TLSv1,TLSv1.1,TLSv1.2" | ||||||||||||||
|
Comment on lines
+60
to
+62
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Don’t enable TLS 1.0/1.1. These are deprecated and should not be forced on the build JVM. - -Djdk.tls.client.protocols="TLSv1,TLSv1.1,TLSv1.2"
+ -Djdk.tls.client.protocols="TLSv1.2,TLSv1.3"📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||
|
|
||||||||||||||
|
Comment on lines
+49
to
+63
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Build depends on a running DB; docker compose can’t guarantee DB is up before build. With dockerize in the builder stage, docker compose up --build will likely fail because images are built before services start. This conflicts with SteVe’s jOOQ/Flyway codegen requirement for a live DB (per retrieved learnings). Leverage the learning: SteVe needs DB during mvn generate-sources. Options:
If you keep dockerize in Dockerfile, remove build from compose for app to avoid misleading users. 🤖 Prompt for AI Agents |
||||||||||||||
| FROM eclipse-temurin:21 | ||||||||||||||
| WORKDIR /app | ||||||||||||||
| ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 | ||||||||||||||
|
|
||||||||||||||
| ARG PORT=8180 | ||||||||||||||
|
|
||||||||||||||
| COPY --from=builder /code/steve/target/steve.jar /app/ | ||||||||||||||
| COPY --from=builder /code/steve/target/libs/ /app/libs/ | ||||||||||||||
|
|
||||||||||||||
| EXPOSE ${PORT} | ||||||||||||||
| EXPOSE 8443 | ||||||||||||||
|
|
||||||||||||||
| CMD ["sh", "-c", "exec java -XX:MaxRAMPercentage=85 -jar /app/steve.jar"] | ||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,42 +1,47 @@ | ||
| version: "3.0" | ||
|
|
||
| volumes: | ||
| db-data: | ||
| external: false | ||
|
|
||
| services: | ||
|
|
||
| db: | ||
| # Pinning MariaDB to point release 10.4.30 works around the issues with the | ||
| # database migrations seen with 10.4.31 in issue #1212. | ||
| # database migrations seen with 10.4.31 in issue https://github.com/steve-community/steve/issues/1212. | ||
| # | ||
| # TODO: Get database migrations to work with the latest point releases of | ||
| # MariaDB 10.4. | ||
| image: mariadb:10.4.30 | ||
| restart: unless-stopped | ||
| ports: | ||
| - 3306:3306 | ||
| - "3306:3306" | ||
| environment: | ||
| MYSQL_RANDOM_ROOT_PASSWORD: "yes" | ||
| MYSQL_DATABASE: stevedb | ||
| MYSQL_USER: steve | ||
| MYSQL_PASSWORD: changeme | ||
| volumes: | ||
| - db-data:/var/lib/mysql | ||
| healthcheck: | ||
| test: [ "CMD", "mysqladmin", "ping", "-h", "localhost" ] | ||
| interval: 5s | ||
| timeout: 3s | ||
| retries: 20 | ||
|
|
||
| app: | ||
| build: | ||
| context: . | ||
| args: | ||
| DB_HOST: host.docker.internal | ||
| DB_PORT: 3306 | ||
| DB_DATABASE: stevedb | ||
| DB_USER: steve | ||
| DB_PASSWORD: changeme | ||
| image: steve:test | ||
|
Comment on lines
+29
to
+37
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Build-time DB args embed secrets and don’t ensure DB is up before build. Two issues:
Consider:
|
||
| restart: unless-stopped | ||
| build: . | ||
| links: | ||
| - "db:mariadb" | ||
| depends_on: | ||
| db: | ||
| condition: service_healthy | ||
| volumes: | ||
| - .:/code | ||
| ports: | ||
| - "8180:8180" | ||
| - "8443:8443" | ||
| environment: | ||
| MYSQL_HOST: mariadb | ||
| MYSQL_PORT: 3306 | ||
| MYSQL_DATABASE: stevedb | ||
| MYSQL_USER: steve | ||
| MYSQL_PASSWORD: changeme | ||
| depends_on: | ||
| - db | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -58,6 +58,10 @@ | |||||||||||||||||||
| <groupId>org.slf4j</groupId> | ||||||||||||||||||||
| <artifactId>slf4j-api</artifactId> | ||||||||||||||||||||
| </dependency> | ||||||||||||||||||||
| <dependency> | ||||||||||||||||||||
| <groupId>ch.qos.logback</groupId> | ||||||||||||||||||||
| <artifactId>logback-classic</artifactId> | ||||||||||||||||||||
| </dependency> | ||||||||||||||||||||
|
Comment on lines
+61
to
+64
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainDon’t pin a logging backend in core; make logback non-transitive Core libraries should depend on slf4j-api only. Make logback optional so downstream runnable modules decide the backend. Apply: - <dependency>
- <groupId>ch.qos.logback</groupId>
- <artifactId>logback-classic</artifactId>
- </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <optional>true</optional>
+ </dependency>🏁 Script executed: #!/bin/bash
# Check for multiple SLF4J bindings across modules
rg -n -C2 -g '**/pom.xml' 'logback-classic|slf4j-simple|log4j-to-slf4j|jul-to-slf4j'Length of output: 1065 🏁 Script executed: #!/bin/bash
# Check for explicit slf4j-api declaration in steve-core/pom.xml
rg -n -C2 '<artifactId>slf4j-api</artifactId>' steve-core/pom.xmlLength of output: 210 Mark logback-classic as optional in steve-core/pom.xml --- steve-core/pom.xml
@@ -61,3 +61,5 @@
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
+ <optional>true</optional>
</dependency>📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||
|
|
||||||||||||||||||||
| <dependency> | ||||||||||||||||||||
| <groupId>com.google.guava</groupId> | ||||||||||||||||||||
|
|
@@ -67,5 +71,9 @@ | |||||||||||||||||||
| <groupId>com.neovisionaries</groupId> | ||||||||||||||||||||
| <artifactId>nv-i18n</artifactId> | ||||||||||||||||||||
| </dependency> | ||||||||||||||||||||
| <dependency> | ||||||||||||||||||||
| <groupId>org.eclipse.jetty.ee10</groupId> | ||||||||||||||||||||
| <artifactId>jetty-ee10-webapp</artifactId> | ||||||||||||||||||||
| </dependency> | ||||||||||||||||||||
| </dependencies> | ||||||||||||||||||||
| </project> | ||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| /* | ||
| * SteVe - SteckdosenVerwaltung - https://github.com/steve-community/steve | ||
| * Copyright (C) 2013-2025 SteVe Community Team | ||
| * All Rights Reserved. | ||
| * | ||
| * This program is free software: you can redistribute it and/or modify | ||
| * it under the terms of the GNU General Public License as published by | ||
| * the Free Software Foundation, either version 3 of the License, or | ||
| * (at your option) any later version. | ||
| * | ||
| * This program is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| * GNU General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU General Public License | ||
| * along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
| */ | ||
| package de.rwth.idsg.steve; | ||
|
|
||
| import org.eclipse.jetty.ee10.webapp.WebAppContext; | ||
|
|
||
| public interface JettyCustomizer { | ||
| void configure(WebAppContext ctx); | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -48,6 +48,14 @@ public static class Paths { | |||||||||||||||||||||||||
| private final String routerEndpointPath; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| private final @Nullable String contextPath; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| public String getLocation() { | ||||||||||||||||||||||||||
| return contextPath + managerMapping + "/home"; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
Comment on lines
+52
to
+55
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Handle nullable contextPath and slash normalization in getLocation(). Current code risks "null..." and double slashes. - public String getLocation() {
- return contextPath + managerMapping + "/home";
- }
+ public String getLocation() {
+ String ctx = (contextPath == null || "/".equals(contextPath)) ? "" : contextPath;
+ if (!managerMapping.startsWith("/")) {
+ // Ensure managerMapping is absolute
+ ctx = ctx + "/";
+ }
+ String base = (ctx.endsWith("/")) ? ctx.substring(0, ctx.length() - 1) : ctx;
+ return base + managerMapping + "/home";
+ }Add unit tests for contextPath = null, "", and "/foo".
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||
| public String getWsPathInfix() { | ||||||||||||||||||||||||||
| return routerEndpointPath + websocketMapping; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
Comment on lines
+56
to
+58
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Normalize join for WebSocket path infix. Avoid missing or duplicate slashes. - public String getWsPathInfix() {
- return routerEndpointPath + websocketMapping;
- }
+ public String getWsPathInfix() {
+ String left = routerEndpointPath.endsWith("/") ? routerEndpointPath.substring(0, routerEndpointPath.length()-1) : routerEndpointPath;
+ String right = websocketMapping.startsWith("/") ? websocketMapping : "/" + websocketMapping;
+ return left + right;
+ }📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| private final Paths paths; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,7 @@ | |
| package de.rwth.idsg.steve.config; | ||
|
|
||
| import com.google.common.collect.Lists; | ||
| import de.rwth.idsg.steve.SteveConfiguration; | ||
| import de.rwth.idsg.steve.ocpp.ws.OcppWebSocketHandshakeHandler; | ||
| import de.rwth.idsg.steve.ocpp.ws.ocpp12.Ocpp12WebSocketEndpoint; | ||
| import de.rwth.idsg.steve.ocpp.ws.ocpp15.Ocpp15WebSocketEndpoint; | ||
|
|
@@ -45,13 +46,13 @@ | |
| @RequiredArgsConstructor | ||
| public class OcppWebSocketConfiguration implements WebSocketConfigurer { | ||
|
|
||
| public static final String PATH_INFIX = "/websocket/CentralSystemService/"; | ||
| public static final Duration PING_INTERVAL = Duration.ofMinutes(15); | ||
| public static final Duration IDLE_TIMEOUT = Duration.ofHours(2); | ||
| public static final int MAX_MSG_SIZE = 8_388_608; // 8 MB for max message size | ||
| public static final Duration WS_PING_INTERVAL = Duration.ofMinutes(15); | ||
| public static final Duration WS_IDLE_TIMEOUT = Duration.ofHours(2); | ||
| public static final int WS_MAX_MSG_SIZE = 8_388_608; // 8 MB for max message size | ||
|
|
||
| private final ChargePointRegistrationService chargePointRegistrationService; | ||
| private final ChargeBoxIdValidator chargeBoxIdValidator; | ||
| private final SteveConfiguration config; | ||
|
|
||
| private final Ocpp12WebSocketEndpoint ocpp12WebSocketEndpoint; | ||
| private final Ocpp15WebSocketEndpoint ocpp15WebSocketEndpoint; | ||
|
|
@@ -60,13 +61,16 @@ public class OcppWebSocketConfiguration implements WebSocketConfigurer { | |
| @Override | ||
| public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { | ||
|
|
||
| OcppWebSocketHandshakeHandler handshakeHandler = new OcppWebSocketHandshakeHandler( | ||
| var handshakeHandler = new OcppWebSocketHandshakeHandler( | ||
| chargeBoxIdValidator, | ||
| new DefaultHandshakeHandler(), | ||
| Lists.newArrayList(ocpp16WebSocketEndpoint, ocpp15WebSocketEndpoint, ocpp12WebSocketEndpoint), | ||
| chargePointRegistrationService); | ||
| chargePointRegistrationService, | ||
| config.getPaths().getWsPathInfix() + "/"); | ||
|
|
||
| registry.addHandler(handshakeHandler.getDummyWebSocketHandler(), PATH_INFIX + "*") | ||
| registry.addHandler( | ||
| handshakeHandler.getDummyWebSocketHandler(), | ||
| config.getPaths().getWsPathInfix() + "/*") | ||
| .setHandshakeHandler(handshakeHandler) | ||
| .setAllowedOrigins("*"); | ||
| } | ||
|
Comment on lines
+71
to
76
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Restrict WebSocket allowed origins. setAllowedOrigins("*") enables any origin. Prefer explicit origins or config-driven patterns. - .setAllowedOrigins("*");
+ // Prefer patterns or a configured list
+ .setAllowedOriginPatterns(config.getSecurity().getAllowedWsOrigins());If no such config exists, introduce one or restrict to known UI origins.
🤖 Prompt for AI Agents |
||
|
|
||
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.
“If present” comment is false; cp will fail when files are absent.
Guard wrapper/.mvn copies to avoid breaking builds in forks/CI without mvnw.
📝 Committable suggestion
🤖 Prompt for AI Agents