bug5628: include username/password in URL construction for YB API

This commit is contained in:
Axel Uhl
2021-10-20 15:28:31 +02:00
parent 13102101ba
commit bd595d7809
4 changed files with 48 additions and 15 deletions
@@ -1,10 +1,12 @@
package com.sap.sailing.domain.yellowbrickadapter.impl;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.net.MalformedURLException;
import java.text.SimpleDateFormat;
import java.util.Optional;
import org.json.simple.parser.ParseException;
import org.junit.Before;
@@ -25,13 +27,15 @@ public class YellowBrickAdapterTest {
@Test
public void testSimpleUrlConstruction() {
final String rmsr2019Url = adapter.getUrlForLatestFix(RMSR2019);
assertEquals("https://yb.tl/API3/Race/rmsr2019/GetPositions?n=1", rmsr2019Url);
final String rmsr2019Url = adapter.getUrlForLatestFix(RMSR2019, /* username */ Optional.of("hello"), /* password */ Optional.of("world"));
assertTrue(rmsr2019Url.startsWith("https://yb.tl/API3/Race/rmsr2019/GetPositions?"));
assertTrue(rmsr2019Url.contains("username=hello"));
assertTrue(rmsr2019Url.contains("password=world"));
}
@Test
public void testGetRaceMetadata() throws IOException, ParseException, java.text.ParseException {
final YellowBrickRace race = adapter.getRaceMetadata(RMSR2019);
final YellowBrickRace race = adapter.getRaceMetadata(RMSR2019, Optional.empty(), Optional.empty());
assertEquals(RMSR2019, race.getRaceUrl());
assertEquals(TimePoint.of(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX").parse("2019-10-26T23:55:01Z")), race.getTimePointOfLastFix());
assertEquals(113, race.getNumberOfCompetitors());
@@ -39,7 +43,7 @@ public class YellowBrickAdapterTest {
@Test
public void testGetFullRaceData() throws MalformedURLException, IOException, ParseException, java.text.ParseException {
final PositionsDocument fullRace = adapter.getStoredData(RMSR2019);
final PositionsDocument fullRace = adapter.getStoredData(RMSR2019, /* username */ Optional.empty(), /* password */ Optional.empty());
assertEquals(113, Util.size(fullRace.getTeams()));
assertEquals(TimePoint.of(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX").parse("2019-10-26T23:55:01Z")), fullRace.getTimePointOfLastFix());
assertEquals(2009, Util.size(Util.filter(fullRace.getTeams(), team->team.getCompetitorName().equals("JYS Jarhead")).iterator().next().getPositions()));
@@ -2,6 +2,7 @@ package com.sap.sailing.domain.yellowbrickadapter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Optional;
import org.json.simple.parser.ParseException;
@@ -34,11 +35,15 @@ public interface YellowBrickTrackingAdapter {
/**
* Obtains the meta-data for the YellowBrick race identified by URL {@code raceUrl}
* @param username TODO
* @param password TODO
*/
YellowBrickRace getRaceMetadata(String raceUrl) throws IOException, ParseException;
YellowBrickRace getRaceMetadata(String raceUrl, Optional<String> username, Optional<String> password) throws IOException, ParseException;
/**
* Retrieves all data stored for the race with {@code raceUrl} so far.
* @param username TODO
* @param password TODO
*/
PositionsDocument getStoredData(String raceUrl) throws MalformedURLException, IOException, ParseException;
PositionsDocument getStoredData(String raceUrl, Optional<String> username, Optional<String> password) throws MalformedURLException, IOException, ParseException;
}
@@ -3,11 +3,14 @@ package com.sap.sailing.domain.yellowbrickadapter.impl;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -79,17 +82,37 @@ public class YellowBrickTrackingAdapterImpl implements YellowBrickTrackingAdapte
/* timeout */ TIMEOUT_FOR_RACE_LOADING.asMillis());
}
String getUrlForLatestFix(String raceUrl) {
return String.format(NUMBER_OF_POSITIONS_URL_TEMPLATE, raceUrl, 1);
String getUrlForLatestFix(String raceUrl, Optional<String> username, Optional<String> password) {
return appendUsernameAndPasswordParameters(String.format(NUMBER_OF_POSITIONS_URL_TEMPLATE, raceUrl, 1), username, password);
}
String getUrlForAllData(String raceUrl) {
return String.format(POSITIONS_SINCE_DATE_URL_TEMPLATE, raceUrl, /* since the beginning of the epoch */ 0l);
private String appendUsernameAndPasswordParameters(String url, Optional<String> username, Optional<String> password) {
final StringBuilder sb = new StringBuilder(url);
appendOptionalParameter(sb, "username", username);
appendOptionalParameter(sb, "password", password);
return sb.toString();
}
private void appendOptionalParameter(StringBuilder urlBuilder, String parameterName, Optional<String> parameterValue) {
if (parameterValue.isPresent() && Util.hasLength(parameterValue.get())) {
urlBuilder.append("&");
urlBuilder.append(parameterName);
urlBuilder.append("=");
try {
urlBuilder.append(URLEncoder.encode(parameterValue.get(), "UTF-8"));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
}
String getUrlForAllData(String raceUrl, Optional<String> username, Optional<String> password) {
return appendUsernameAndPasswordParameters(String.format(POSITIONS_SINCE_DATE_URL_TEMPLATE, raceUrl, /* since the beginning of the epoch */ 0l), username, password);
}
@Override
public YellowBrickRace getRaceMetadata(String raceUrl) throws IOException, ParseException {
final String url = getUrlForLatestFix(raceUrl);
public YellowBrickRace getRaceMetadata(String raceUrl, Optional<String> username, Optional<String> password) throws IOException, ParseException {
final String url = getUrlForLatestFix(raceUrl, username, password);
final PositionsDocument doc = getPositionsDocumentForUrl(url);
return new YellowBrickRaceImpl(raceUrl, doc.getTimePointOfLastFix(), Util.size(doc.getTeams()));
}
@@ -103,8 +126,8 @@ public class YellowBrickTrackingAdapterImpl implements YellowBrickTrackingAdapte
}
@Override
public PositionsDocument getStoredData(String raceUrl) throws MalformedURLException, IOException, ParseException {
return getPositionsDocumentForUrl(getUrlForAllData(raceUrl));
public PositionsDocument getStoredData(String raceUrl, Optional<String> username, Optional<String> password) throws MalformedURLException, IOException, ParseException {
return getPositionsDocumentForUrl(getUrlForAllData(raceUrl, username, password));
}
@Override
@@ -6310,7 +6310,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
@Override
public Pair<String, List<YellowBrickRaceRecordDTO>> listYellowBrickRacesInEvent(YellowBrickConfigurationWithSecurityDTO config) throws Exception {
final YellowBrickRace raceMetadata = getYellowBrickTrackingAdapter().getRaceMetadata(config.getRaceUrl());
final YellowBrickRace raceMetadata = getYellowBrickTrackingAdapter().getRaceMetadata(config.getRaceUrl(),
Optional.ofNullable(config.getUsername()), Optional.ofNullable(config.getPassword()));
return new Pair<>(raceMetadata.getRaceUrl(),
Collections.singletonList(new YellowBrickRaceRecordDTO(config.getName(),
raceMetadata.getRaceUrl(), hasRememberedRegatta(raceMetadata.getRaceId()),