Skip to content

Commit 3c22899

Browse files
fix merge conflict
2 parents 2d4fcfe + 8d007ea commit 3c22899

16 files changed

+135
-110
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ Screenshots
118118
9. [Operations - OCPP v1.5](website/screenshots/ocpp15.png)
119119
10. [Settings](website/screenshots/settings.png)
120120
121+
122+
GDPR
123+
-----
124+
If you are in the EU and offer vehicle charging to other people using SteVe, keep in mind that you have to comply to the General Data Protection Regulation (GDPR) as SteVe processes charging transactions, which can be considered personal data.
125+
121126
Are you having issues?
122127
-----
123128
See the [FAQ](https://github.com/RWTH-i5-IDSG/steve/wiki/FAQ)

pom.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,24 @@
140140
</configuration>
141141
</plugin>
142142

143+
<plugin>
144+
<groupId>pl.project13.maven</groupId>
145+
<artifactId>git-commit-id-plugin</artifactId>
146+
<version>2.2.4</version>
147+
<executions>
148+
<execution>
149+
<phase>initialize</phase>
150+
<goals>
151+
<goal>revision</goal>
152+
</goals>
153+
</execution>
154+
</executions>
155+
<configuration>
156+
<failOnNoGitDirectory>false</failOnNoGitDirectory>
157+
<failOnUnableToExtractRepoInfo>false</failOnUnableToExtractRepoInfo>
158+
</configuration>
159+
</plugin>
160+
143161
<!-- Read from main.properties the DB configuration -->
144162
<plugin>
145163
<groupId>org.codehaus.mojo</groupId>

src/main/java/de/rwth/idsg/steve/SteveConfiguration.java

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package de.rwth.idsg.steve;
22

3+
import de.rwth.idsg.steve.ocpp.ws.custom.WsSessionSelectStrategy;
34
import de.rwth.idsg.steve.ocpp.ws.custom.WsSessionSelectStrategyEnum;
45
import de.rwth.idsg.steve.utils.PropertiesFileLoader;
56
import lombok.Builder;
67
import lombok.Getter;
8+
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
9+
import org.springframework.security.crypto.password.PasswordEncoder;
710

811
/**
912
* @author Sevket Goekay <goekay@dbis.rwth-aachen.de>
@@ -30,6 +33,7 @@ public enum SteveConfiguration {
3033

3134
private final String contextPath;
3235
private final String steveVersion;
36+
private final String gitDescribe;
3337
private final ApplicationProfile profile;
3438
private final Ocpp ocpp;
3539
private final Auth auth;
@@ -41,6 +45,7 @@ public enum SteveConfiguration {
4145

4246
contextPath = sanitizeContextPath(p.getOptionalString("context.path"));
4347
steveVersion = p.getString("steve.version");
48+
gitDescribe = useFallbackIfNotSet(p.getOptionalString("git.describe"), null);
4449
profile = ApplicationProfile.fromName(p.getString("profile"));
4550

4651
jetty = Jetty.builder()
@@ -63,9 +68,12 @@ public enum SteveConfiguration {
6368
.sqlLogging(p.getBoolean("db.sql.logging"))
6469
.build();
6570

71+
PasswordEncoder encoder = new BCryptPasswordEncoder();
72+
6673
auth = Auth.builder()
74+
.passwordEncoder(encoder)
6775
.userName(p.getString("auth.user"))
68-
.password(p.getString("auth.password"))
76+
.encodedPassword(encoder.encode(p.getString("auth.password")))
6977
.build();
7078

7179
ocpp = Ocpp.builder()
@@ -77,6 +85,26 @@ public enum SteveConfiguration {
7785
validate();
7886
}
7987

88+
public String getSteveCompositeVersion() {
89+
if (gitDescribe == null) {
90+
return steveVersion;
91+
} else {
92+
return steveVersion + "-g" + gitDescribe;
93+
}
94+
}
95+
96+
private static String useFallbackIfNotSet(String value, String fallback) {
97+
if (value == null) {
98+
// if the property is optional, value will be null
99+
return fallback;
100+
} else if (value.startsWith("${")) {
101+
// property value variables start with "${" (if maven is not used, the value will not be set)
102+
return fallback;
103+
} else {
104+
return value;
105+
}
106+
}
107+
80108
private String sanitizeContextPath(String s) {
81109
if (s == null || "/".equals(s)) {
82110
return "";
@@ -131,15 +159,16 @@ public static class DB {
131159
// Credentials for Web interface access
132160
@Builder @Getter
133161
public static class Auth {
162+
private final PasswordEncoder passwordEncoder;
134163
private final String userName;
135-
private final String password;
164+
private final String encodedPassword;
136165
}
137166

138167
// OCPP-related configuration
139168
@Builder @Getter
140169
public static class Ocpp {
141170
private final boolean autoRegisterUnknownStations;
142-
private final WsSessionSelectStrategyEnum wsSessionSelectStrategy;
171+
private final WsSessionSelectStrategy wsSessionSelectStrategy;
143172
}
144173

145174
}

src/main/java/de/rwth/idsg/steve/config/OcppConfiguration.java

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33
import de.rwth.idsg.steve.ocpp.soap.LoggingFeatureProxy;
44
import de.rwth.idsg.steve.ocpp.soap.MediatorInInterceptor;
55
import de.rwth.idsg.steve.ocpp.soap.MessageIdInterceptor;
6-
import de.rwth.idsg.steve.ocpp.ws.custom.AlwaysLastStrategy;
7-
import de.rwth.idsg.steve.ocpp.ws.custom.RoundRobinStrategy;
8-
import de.rwth.idsg.steve.ocpp.ws.custom.WsSessionSelectStrategy;
96
import org.apache.cxf.Bus;
107
import org.apache.cxf.bus.spring.SpringBus;
118
import org.apache.cxf.common.logging.LogUtils;
@@ -71,18 +68,6 @@ public SpringBus springBus() {
7168
return new SpringBus();
7269
}
7370

74-
@Bean
75-
public WsSessionSelectStrategy sessionSelectStrategy() {
76-
switch (CONFIG.getOcpp().getWsSessionSelectStrategy()) {
77-
case ALWAYS_LAST:
78-
return new AlwaysLastStrategy();
79-
case ROUND_ROBIN:
80-
return new RoundRobinStrategy();
81-
default:
82-
throw new RuntimeException("Could not find a valid WsSessionSelectStrategy");
83-
}
84-
}
85-
8671
private void createOcppService(Object serviceBean, String address,
8772
List<Interceptor<? extends Message>> interceptors,
8873
Collection<? extends Feature> features) {

src/main/java/de/rwth/idsg/steve/config/SecurityConfiguration.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,17 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
2727
/**
2828
* Password encoding changed with spring-security 5.0.0. We either have to use a prefix before the password to
2929
* indicate which actual encoder {@link DelegatingPasswordEncoder} should use [1, 2] or specify the encoder as we do.
30-
* {@link NoOpPasswordEncoder} is deprecated because it is not secure since it is not a one way hash function and
31-
* uses plain text matching, but is good enough for our simple user management and login authorization case.
3230
*
3331
* [1] https://spring.io/blog/2017/11/01/spring-security-5-0-0-rc1-released#password-storage-format
3432
* [2] {@link PasswordEncoderFactories#createDelegatingPasswordEncoder()}
3533
*/
3634
@Autowired
3735
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
3836
auth.inMemoryAuthentication()
39-
.passwordEncoder(NoOpPasswordEncoder.getInstance())
40-
.withUser(CONFIG.getAuth().getUserName())
41-
.password(CONFIG.getAuth().getPassword())
42-
.roles("ADMIN");
43-
37+
.passwordEncoder(CONFIG.getAuth().getPasswordEncoder())
38+
.withUser(CONFIG.getAuth().getUserName())
39+
.password(CONFIG.getAuth().getEncodedPassword())
40+
.roles("ADMIN");
4441
}
4542

4643
@Override

src/main/java/de/rwth/idsg/steve/ocpp/ws/AbstractWebSocketEndpoint.java

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
package de.rwth.idsg.steve.ocpp.ws;
22

3+
import com.google.common.base.Strings;
34
import de.rwth.idsg.steve.config.WebSocketConfiguration;
45
import de.rwth.idsg.steve.ocpp.OcppVersion;
5-
import de.rwth.idsg.steve.ocpp.ws.custom.WsSessionSelectStrategy;
66
import de.rwth.idsg.steve.ocpp.ws.data.CommunicationContext;
77
import de.rwth.idsg.steve.ocpp.ws.data.SessionContext;
88
import de.rwth.idsg.steve.ocpp.ws.pipeline.IncomingPipeline;
99
import de.rwth.idsg.steve.repository.OcppServerRepository;
1010
import de.rwth.idsg.steve.service.NotificationService;
1111
import org.joda.time.DateTime;
12-
import org.slf4j.Logger;
13-
import org.slf4j.LoggerFactory;
1412
import org.springframework.beans.factory.annotation.Autowired;
1513
import org.springframework.web.socket.BinaryMessage;
1614
import org.springframework.web.socket.CloseStatus;
@@ -34,29 +32,25 @@
3432
* @since 17.03.2015
3533
*/
3634
public abstract class AbstractWebSocketEndpoint implements WebSocketHandler {
37-
private final Logger log = LoggerFactory.getLogger(getClass());
3835

3936
@Autowired private ScheduledExecutorService service;
4037
@Autowired private OcppServerRepository ocppServerRepository;
4138
@Autowired private FutureResponseContextStore futureResponseContextStore;
42-
@Autowired private WsSessionSelectStrategy wsSessionSelectStrategy;
4339
@Autowired private NotificationService notificationService;
4440

4541
public static final String CHARGEBOX_ID_KEY = "CHARGEBOX_ID_KEY";
4642

47-
private IncomingPipeline pipeline;
48-
private SessionContextStoreImpl sessionContextStore;
49-
43+
private final SessionContextStoreImpl sessionContextStore = new SessionContextStoreImpl();
5044
private final List<Consumer<String>> connectedCallbackList = new ArrayList<>();
5145
private final List<Consumer<String>> disconnectedCallbackList = new ArrayList<>();
52-
5346
private final Object sessionContextLock = new Object();
5447

48+
private IncomingPipeline pipeline;
49+
5550
public abstract OcppVersion getVersion();
5651

5752
public void init(IncomingPipeline pipeline) {
5853
this.pipeline = pipeline;
59-
sessionContextStore = new SessionContextStoreImpl(wsSessionSelectStrategy);
6054

6155
connectedCallbackList.add((chargeBoxId) -> notificationService.ocppStationWebSocketConnected(chargeBoxId));
6256
disconnectedCallbackList.add((chargeBoxId) -> notificationService.ocppStationWebSocketDisconnected(chargeBoxId));
@@ -82,6 +76,12 @@ private void handleTextMessage(WebSocketSession session, TextMessage webSocketMe
8276
String incomingString = webSocketMessage.getPayload();
8377
String chargeBoxId = getChargeBoxId(session);
8478

79+
// https://github.com/RWTH-i5-IDSG/steve/issues/66
80+
if (Strings.isNullOrEmpty(incomingString)) {
81+
WebSocketLogger.receivedEmptyText(chargeBoxId, session);
82+
return;
83+
}
84+
8585
WebSocketLogger.receivedText(chargeBoxId, session, incomingString);
8686

8787
CommunicationContext context = new CommunicationContext(session, chargeBoxId);
@@ -92,8 +92,6 @@ private void handleTextMessage(WebSocketSession session, TextMessage webSocketMe
9292

9393
private void handlePongMessage(WebSocketSession session) {
9494
WebSocketLogger.receivedPong(getChargeBoxId(session), session);
95-
96-
// TODO: Not sure about the following. Should update DB? Should call directly repo?
9795
ocppServerRepository.updateChargeboxHeartbeat(getChargeBoxId(session), DateTime.now());
9896
}
9997

@@ -106,7 +104,7 @@ public void afterConnectionEstablished(WebSocketSession session) throws Exceptio
106104
// Just to keep the connection alive, such that the servers do not close
107105
// the connection because of a idle timeout, we ping-pong at fixed intervals.
108106
ScheduledFuture pingSchedule = service.scheduleAtFixedRate(
109-
new PingTask(session),
107+
new PingTask(chargeBoxId, session),
110108
WebSocketConfiguration.PING_INTERVAL,
111109
WebSocketConfiguration.PING_INTERVAL,
112110
TimeUnit.MINUTES);
@@ -151,8 +149,7 @@ public void afterConnectionClosed(WebSocketSession session, CloseStatus closeSta
151149

152150
@Override
153151
public void handleTransportError(WebSocketSession session, Throwable throwable) throws Exception {
154-
log.error("Oops", throwable);
155-
// TODO: Do something about this
152+
WebSocketLogger.transportError(getChargeBoxId(session), session, throwable);
156153
}
157154

158155
@Override

src/main/java/de/rwth/idsg/steve/ocpp/ws/PingTask.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,18 @@
1717
@Slf4j
1818
@RequiredArgsConstructor
1919
public class PingTask implements Runnable {
20+
private final String chargeBoxId;
2021
private final WebSocketSession session;
2122

2223
private static final PingMessage PING_MESSAGE = new PingMessage(ByteBuffer.wrap("ping".getBytes(UTF_8)));
2324

2425
@Override
2526
public void run() {
26-
log.info("[id={}] Sending ping message", session.getId());
27+
WebSocketLogger.sendingPing(chargeBoxId, session);
2728
try {
2829
session.sendMessage(PING_MESSAGE);
2930
} catch (IOException e) {
30-
log.error("[id={}] Ping failed", session.getId());
31+
WebSocketLogger.pingError(chargeBoxId, session, e);
3132
// TODO: Do something about this
3233
}
3334
}

src/main/java/de/rwth/idsg/steve/ocpp/ws/SessionContextStoreImpl.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import java.util.concurrent.ScheduledFuture;
2020
import java.util.concurrent.locks.Lock;
2121

22+
import static de.rwth.idsg.steve.SteveConfiguration.CONFIG;
23+
2224
/**
2325
* @author Sevket Goekay <goekay@dbis.rwth-aachen.de>
2426
* @since 17.03.2015
@@ -34,11 +36,7 @@ public class SessionContextStoreImpl implements SessionContextStore {
3436

3537
private final Striped<Lock> locks = Striped.lock(16);
3638

37-
private final WsSessionSelectStrategy wsSessionSelectStrategy;
38-
39-
public SessionContextStoreImpl(WsSessionSelectStrategy wsSessionSelectStrategy) {
40-
this.wsSessionSelectStrategy = wsSessionSelectStrategy;
41-
}
39+
private final WsSessionSelectStrategy wsSessionSelectStrategy = CONFIG.getOcpp().getWsSessionSelectStrategy();
4240

4341
@Override
4442
public void add(String chargeBoxId, WebSocketSession session, ScheduledFuture pingSchedule) {

src/main/java/de/rwth/idsg/steve/ocpp/ws/WebSocketLogger.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
* @since 10.05.2018
1010
*/
1111
@Slf4j
12-
public class WebSocketLogger {
12+
public final class WebSocketLogger {
13+
14+
private WebSocketLogger() { }
1315

1416
public static void connected(String chargeBoxId, WebSocketSession session) {
1517
log.info("[chargeBoxId={}, sessionId={}] Connection is established", chargeBoxId, session.getId());
@@ -19,6 +21,14 @@ public static void closed(String chargeBoxId, WebSocketSession session, CloseSta
1921
log.warn("[chargeBoxId={}, sessionId={}] Connection is closed, status: {}", chargeBoxId, session.getId(), closeStatus);
2022
}
2123

24+
public static void sending(String chargeBoxId, WebSocketSession session, String msg) {
25+
log.info("[chargeBoxId={}, sessionId={}] Sending: {}", chargeBoxId, session.getId(), msg);
26+
}
27+
28+
public static void sendingPing(String chargeBoxId, WebSocketSession session) {
29+
log.debug("[chargeBoxId={}, sessionId={}] Sending ping message", chargeBoxId, session.getId());
30+
}
31+
2232
public static void receivedPong(String chargeBoxId, WebSocketSession session) {
2333
log.debug("[chargeBoxId={}, sessionId={}] Received pong message", chargeBoxId, session.getId());
2434
}
@@ -27,7 +37,19 @@ public static void receivedText(String chargeBoxId, WebSocketSession session, St
2737
log.info("[chargeBoxId={}, sessionId={}] Received: {}", chargeBoxId, session.getId(), msg);
2838
}
2939

30-
public static void sending(String chargeBoxId, WebSocketSession session, String msg) {
31-
log.info("[chargeBoxId={}, sessionId={}] Sending: {}", chargeBoxId, session.getId(), msg);
40+
public static void receivedEmptyText(String chargeBoxId, WebSocketSession session) {
41+
log.warn("[chargeBoxId={}, sessionId={}] Received empty text message. Will pretend this never happened.", chargeBoxId, session.getId());
42+
}
43+
44+
public static void pingError(String chargeBoxId, WebSocketSession session, Throwable t) {
45+
if (log.isErrorEnabled()) {
46+
log.error("[chargeBoxId=" + chargeBoxId + ", sessionId=" + session.getId() + "] Ping error", t);
47+
}
48+
}
49+
50+
public static void transportError(String chargeBoxId, WebSocketSession session, Throwable t) {
51+
if (log.isErrorEnabled()) {
52+
log.error("[chargeBoxId=" + chargeBoxId + ", sessionId=" + session.getId() + "] Transport error", t);
53+
}
3254
}
3355
}

src/main/java/de/rwth/idsg/steve/ocpp/ws/custom/AlwaysLastStrategy.java

Lines changed: 0 additions & 24 deletions
This file was deleted.

0 commit comments

Comments
 (0)