From 0d55a7dddf7ef86161b232c5d2c71e1a767d7ec2 Mon Sep 17 00:00:00 2001
From: Axel Uhl
Date: Tue, 13 Jul 2021 18:35:25 +0200
Subject: [PATCH] bug5311: export leaderboard group display name; tolerate
unauthenticated requests and use null as bearer token then
---
.../jaxrs/api/CompareServersResource.java | 51 ++++++++++++++++---
.../jaxrs/api/LeaderboardGroupsResource.java | 1 +
.../api/MigrateLeaderboardgroupResource.java | 8 ++-
.../webservices/api/v1/compareServers.html | 27 +++++-----
.../server/interfaces/RacingEventService.java | 3 +-
.../server/impl/RacingEventServiceImpl.java | 12 ++---
6 files changed, 71 insertions(+), 31 deletions(-)
diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompareServersResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompareServersResource.java
index f0b47abfe5b..bcf8b9d7924 100644
--- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompareServersResource.java
+++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompareServersResource.java
@@ -43,8 +43,8 @@ import com.sap.sse.util.HttpUrlConnectionHelper;
public class CompareServersResource extends AbstractSailingServerResource {
private static final Logger logger = Logger.getLogger(CompareServersResource.class.getName());
- private static final String LEADERBOARDGROUPSIDENTIFIABLEPATH = "/sailingserver/api/v1/leaderboardgroups/identifiable";
private static final String LEADERBOARDGROUPSPATH = "/sailingserver/api/v1/leaderboardgroups";
+ private static final String LEADERBOARDGROUPSIDENTIFIABLEPATH = LEADERBOARDGROUPSPATH+"/identifiable";
/**
* The list of keys that are compared during a compare run.
*/
@@ -83,6 +83,45 @@ public class CompareServersResource extends AbstractSailingServerResource {
@Context
UriInfo uriInfo;
+ /**
+ * @param server1
+ * optional; if not provided, the server receiving this request will act as the default for "server1"
+ * @param user1
+ * the username for authenticating the request for {@code server1}, together with {@code password1};
+ * alternatively to {@code user1} and {@code password1} clients may specify {@code bearer1}. If none of
+ * these are provided, this request's authentication will be used to obtain a bearer token for
+ * {@code server1}.
+ * @param password1
+ * use together with {@code user1} to provide authentication for the requests for {@code server1}
+ * (defaulting to this server).
+ * @param bearer1
+ * alternative for {@code user1}/{@code password1}, specifying a bearer token that is used to
+ * authenticate a user on {@code server1} (which defaults to the server handling this request). If
+ * neither of {@code user1}, {@code password1} and {@core bearer1} are provided, this request's
+ * authentication is used to obtain a bearer token which is then used to authenticate the requests for
+ * {@code server1}.
+ * @param server2
+ * mandatory; specifies the host name or IP address of the host against which to compare the
+ * {@code server1} content
+ * @param user2
+ * the username for authenticating the request for {@code server2}, together with {@code password2};
+ * alternatively to {@code user2} and {@code password2} clients may specify {@code bearer2}. If none of
+ * these are provided, this request's authentication will be used to obtain a bearer token for
+ * {@code server2}, assuming that the server responding to this request and {@code server2} share a
+ * common {@code SecurityService} through replication.
+ * @param password2
+ * use together with {@code user2} to provide authentication for the requests for {@code server2}.
+ * @param bearer2
+ * alternative for {@code user2}/{@code password2}, specifying a bearer token that is used to
+ * authenticate a user on {@code server2}. If neither of {@code user2}, {@code password2} and
+ * {@core bearer2} are provided, this request's authentication is used to obtain a bearer token which is
+ * then used to authenticate the requests for {@code server1}, assuming that the server responding to
+ * this request and {@code server2} share a common {@code SecurityService} through replication.
+ * @param leaderboardgroupUUID
+ * can optionally be used to specify a set of UUIDs identifying leaderboard groups to compare. If not
+ * specified (represented as an {@link Set#isEmpty() empty} set), all leaderboard groups found on both,
+ * {@code server1} and {@code server2} will be compared.
+ */
@POST
@Produces("application/json;charset=UTF-8")
public Response compareServers(
@@ -101,11 +140,7 @@ public class CompareServersResource extends AbstractSailingServerResource {
effectiveServer1 = !Util.hasLength(server1) ? uriInfo.getBaseUri().getAuthority() : server1;
if (!validateParameters(effectiveServer1, server2, uuidset, user1, user2, password1, password2, bearer1, bearer2)) {
response = badRequest("Specify two server names and optionally a set of valid leaderboardgroup UUIDs.");
- }
- else if (getSecurityService().getCurrentUser() == null) {
- response = badRequest("Provide valid user.");
- }
- else {
+ } else {
final String token1 = getService().getOrCreateTargetServerBearerToken(effectiveServer1, user1, password1, bearer1);
final String token2 = getService().getOrCreateTargetServerBearerToken(server2, user2, password2, bearer2);
result.put(effectiveServer1, new HashSet<>());
@@ -166,6 +201,7 @@ public class CompareServersResource extends AbstractSailingServerResource {
private boolean validateParameters(String server1, String server2, Set uuidset, String user1, String user2,
String password1, String password2, String bearer1, String bearer2) {
+ // FIXME bug5311: the following two statements may be redundant; re-design...
boolean result = (validateParameters(user1, password1, bearer1) || validateParameters(user2, password2, bearer2));
result = validateParameters(server1, server2, uuidset);
return result;
@@ -186,6 +222,9 @@ public class CompareServersResource extends AbstractSailingServerResource {
return Util.hasLength(server1) && Util.hasLength(server2);
}
+ /**
+ * Valid combinations: user+password; bearer; nothing
+ */
private boolean validateParameters(String user, String password, String bearer) {
return (((Util.hasLength(user) && Util.hasLength(password) && !Util.hasLength(bearer))
|| (!Util.hasLength(user) && !Util.hasLength(password) && Util.hasLength(bearer)))
diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardGroupsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardGroupsResource.java
index c6360f9f837..5b32f6dd8b8 100644
--- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardGroupsResource.java
+++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardGroupsResource.java
@@ -132,6 +132,7 @@ public class LeaderboardGroupsResource extends AbstractSailingServerResource {
JSONObject jsonLeaderboardGroup = new JSONObject();
jsonLeaderboardGroup.put(LeaderboardGroupConstants.NAME, leaderboardGroup.getName());
jsonLeaderboardGroup.put(LeaderboardGroupConstants.ID, leaderboardGroup.getId().toString());
+ jsonLeaderboardGroup.put(LeaderboardGroupConstants.DISPLAYNAME, leaderboardGroup.getDisplayName());
jsonLeaderboardGroup.put(LeaderboardGroupConstants.DESCRIPTION, leaderboardGroup.getDescription());
jsonLeaderboardGroup.put(LeaderboardGroupConstants.TIMEPOINT, timePoint.toString());
final Set eventsReferencingLeaderboardGroup = new HashSet<>();
diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/MigrateLeaderboardgroupResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/MigrateLeaderboardgroupResource.java
index 39a571b21c5..c9017767e4c 100644
--- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/MigrateLeaderboardgroupResource.java
+++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/MigrateLeaderboardgroupResource.java
@@ -54,10 +54,8 @@ public class MigrateLeaderboardgroupResource extends AbstractSailingServerResour
@FormParam("bearer1") String bearer1,
@FormParam("bearer2") String bearer2) {
Response response;
- final String baseServerBearerToken = getService().getOrCreateTargetServerBearerToken(baseServer, user1,
- password1, bearer1);
- final String dedicatedServerBearerToken = getService().getOrCreateTargetServerBearerToken(dedicatedServer,
- user2, password2, bearer2);
+ final String baseServerBearerToken = getService().getOrCreateTargetServerBearerToken(baseServer, user1, password1, bearer1);
+ final String dedicatedServerBearerToken = getService().getOrCreateTargetServerBearerToken(dedicatedServer, user2, password2, bearer2);
try {
final JSONObject result = new JSONObject();
final Util.Pair mdi = doMDI(baseServer, dedicatedServer, requestedLeaderboardGroups,
@@ -85,7 +83,7 @@ public class MigrateLeaderboardgroupResource extends AbstractSailingServerResour
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces("application/json;charset=UTF-8")
- public Response moveToArchive(
+ public Response moveToArchiveServer(
@FormParam("archive") String archiveServer,
@FormParam("dedicated") String dedicatedServer,
@FormParam("UUID[]") Set requestedLeaderboardGroups,
diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/compareServers.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/compareServers.html
index 329cc07d681..3be521a778a 100644
--- a/java/com.sap.sailing.server.gateway/webservices/api/v1/compareServers.html
+++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/compareServers.html
@@ -13,15 +13,15 @@
Description:
Compares two SAP Sailing Analytics servers based on the content.
- The return contains either the missing leaderboardgroup name and id or
+ The response contains either the missing leaderboardgroup name and id or
if the leaderboardgroupnames match on both servers the missing parts
within the leaderboardgroups. If the servers contain the exact same
content the return will just have the given server hostnames in it.
You may also query for a specific leaderboardgroup id; there the same
logic applies. The HTTP return code will be 409 if a mismatch is
detected in your query, if equal content is present on both servers
- the response code will be 200. The caller needs authorization with a
- valid user.
+ the response code will be 200. Authorization must be provided in case
+ content is to be compared that is not publicly readable.
@@ -41,16 +41,17 @@
| Optional form parameters: |
- server1, the hostname for the first server. Defaults to the server that you target your request
- leaderboardgroupUUID[], the leaderboardgroup UUID you want to compare.
- Use multiple times if you need to compare more then one
- leaderboardgroup.
- user1, the user to authenticate against server1.
- password1, password for user1.
- bearer1, you might provide a bearer token instead of user1 and password1.
- user2, see user1.
- password2, see password1.
- bearer2, see bearer1.
+ server1, the hostname for the first server. Defaults to the target of your request
+ leaderboardgroupUUID[], the leaderboardgroup UUID you want to compare.
+ Use multiple times if you need to compare more than one leaderboardgroup.
+ user1, the user to authenticate against server1. If provided, password1 must be provided, too.
+ password1, password for user1.
+ bearer1, you might provide a bearer token instead of user1 and password1. If neither this
+ bearer token nor user/password is provided, the request's authentication information is used to infer
+ user credentials. If no user can be authenticated, only publicly readable content will be considered.
+ user2, see user1.
+ password2, see password1.
+ bearer2, see bearer1.
|
diff --git a/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/interfaces/RacingEventService.java b/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/interfaces/RacingEventService.java
index 79f970e07de..589494d8381 100644
--- a/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/interfaces/RacingEventService.java
+++ b/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/interfaces/RacingEventService.java
@@ -1008,7 +1008,8 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
/**
* Constructs a Bearer token for a given remote Server, either using a given username and password, or a given
* bearer token. If neither of those are provided the current user will be used to create a bearer token. Provide
- * only username and password or bearer token, not the three of them.
+ * only username and password or bearer token, not the three of them. If none is provided but there is no user
+ * currently authenticated, {@code null} will be returned.
*/
String getOrCreateTargetServerBearerToken(String targetServerUrlAsString, String targetServerUsername,
String targetServerPassword, String targetServerBearerToken);
diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java
index be252c7637a..ae89f9e3d0f 100644
--- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java
+++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java
@@ -5107,7 +5107,7 @@ implements RacingEventService, ClearStateTestSupport, RegattaListener, Leaderboa
@Override
public String getOrCreateTargetServerBearerToken(String targetServerUrlAsString, String targetServerUsername,
String targetServerPassword, String targetServerBearerToken) {
- if (Util.hasLength(targetServerUsername) && Util.hasLength(targetServerPassword)
+ if ((Util.hasLength(targetServerUsername) || Util.hasLength(targetServerPassword))
&& Util.hasLength(targetServerBearerToken)) {
IllegalArgumentException e = new IllegalArgumentException(
"Please use either username/password or bearer token, not both.");
@@ -5117,15 +5117,15 @@ implements RacingEventService, ClearStateTestSupport, RegattaListener, Leaderboa
final User user = getSecurityService().getCurrentUser();
// Default to current user's token
final String effectiveTargetServerBearerToken;
- if (!Util.hasLength(targetServerUsername) && !Util.hasLength(targetServerPassword)
- && !Util.hasLength(targetServerBearerToken)) {
- effectiveTargetServerBearerToken = getSecurityService().getOrCreateAccessToken(user.getName());
+ if (!Util.hasLength(targetServerUsername) && !Util.hasLength(targetServerPassword) && !Util.hasLength(targetServerBearerToken)) {
+ effectiveTargetServerBearerToken = user == null ? null : getSecurityService().getOrCreateAccessToken(user.getName());
} else {
effectiveTargetServerBearerToken = targetServerBearerToken;
}
final String token = (!Util.hasLength(effectiveTargetServerBearerToken)
- ? RemoteServerUtil.resolveBearerTokenForRemoteServer(targetServerUrlAsString, targetServerUsername,
- targetServerPassword)
+ ? targetServerUsername != null ?
+ RemoteServerUtil.resolveBearerTokenForRemoteServer(targetServerUrlAsString, targetServerUsername, targetServerPassword) :
+ null // in case no effective bearer token has been provided but no user name either
: effectiveTargetServerBearerToken);
return token;
}