From c71f01a730ab8657e734815a80ca3e1170f6465b Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Fri, 21 Jun 2019 17:24:10 +0200 Subject: [PATCH 01/69] Bug 4960: added preferences for TrackedEvents --- .../preferences/model/SailingPreferences.java | 1 + .../model/TrackedEventPreference.java | 83 +++++++++++++++++++ .../model/TrackedEventPreferences.java | 35 ++++++++ 3 files changed, 119 insertions(+) create mode 100644 java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java create mode 100644 java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreferences.java diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/SailingPreferences.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/SailingPreferences.java index 236c6f087a8..a089e5c2a29 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/SailingPreferences.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/SailingPreferences.java @@ -7,4 +7,5 @@ package com.sap.sailing.server.impl.preferences.model; public interface SailingPreferences { public static final String NOTIFICATION_PREFERENCES_PREFIX = "sailing.notifications."; public static final String STORED_DATAMINING_QUERY_PREFERENCES = "sailing.datamining.storedqueries"; + public static final String TRACKED_EVENTS_PREFERENCES = "sailing.profile.trackedevents"; } diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java new file mode 100644 index 00000000000..47179ecb43f --- /dev/null +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java @@ -0,0 +1,83 @@ +package com.sap.sailing.server.impl.preferences.model; + +import java.util.UUID; + +import com.sap.sse.common.settings.generic.AbstractGenericSerializableSettings; +import com.sap.sse.common.settings.generic.BooleanSetting; +import com.sap.sse.common.settings.generic.UUIDSetting; + +public class TrackedEventPreference extends AbstractGenericSerializableSettings { + private static final long serialVersionUID = 234711768869820003L; + + private transient UUIDSetting uuid; + private transient UUIDSetting eventId; + private transient UUIDSetting regattaId; + private transient UUIDSetting trackedElementId; + private transient BooleanSetting isArchived; + + public TrackedEventPreference() { + uuid = new UUIDSetting("uuid", this); + eventId = new UUIDSetting("eventId", this); + regattaId = new UUIDSetting("regattaId", this); + trackedElementId = new UUIDSetting("trackedElementId", this); + isArchived = new BooleanSetting("isArchived", this); + } + + /** copy constructor */ + public TrackedEventPreference(TrackedEventPreference other) { + this(); + uuid.setValue(other.getUuid()); + eventId.setValue(other.getEventId()); + regattaId.setValue(other.getRegattaId()); + trackedElementId.setValue(other.getTrackedElementId()); + isArchived.setValue(other.getIsArchived()); + } + + /** copy constructor with new archived state */ + public TrackedEventPreference(TrackedEventPreference other, boolean isArchived) { + this(); + uuid.setValue(other.getUuid()); + eventId.setValue(other.getEventId()); + regattaId.setValue(other.getRegattaId()); + trackedElementId.setValue(other.getTrackedElementId()); + this.isArchived.setValue(isArchived); + } + + public TrackedEventPreference(UUID uuid, UUID eventId, UUID regattaId, UUID trackedElementId, boolean isArchived) { + this(); + this.uuid.setValue(uuid); + this.eventId.setValue(eventId); + this.regattaId.setValue(regattaId); + this.trackedElementId.setValue(trackedElementId); + this.isArchived.setValue(isArchived); + } + + @Override + protected void addChildSettings() { + // We do not create the Setting instances here, because access to the RacingEventService would not be given. + // Doing this, Java/GWT Serialization isn't working anymore. Because the preferences are only serialized as JSON + // in the backend an transferred as DTO to the frontend, this isn't a problem. Due to usage of BoatClass and + // Competitor domain objects, it wouldn't be GWT compatible anyway. + // The usage of Java Serialization isn't planned by now, either. + } + + public UUID getUuid() { + return uuid.getValue(); + } + + public UUID getEventId() { + return eventId.getValue(); + } + + public UUID getRegattaId() { + return regattaId.getValue(); + } + + public UUID getTrackedElementId() { + return trackedElementId.getValue(); + } + + public boolean getIsArchived() { + return isArchived.getValue(); + } +} diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreferences.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreferences.java new file mode 100644 index 00000000000..076949ca7c7 --- /dev/null +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreferences.java @@ -0,0 +1,35 @@ +package com.sap.sailing.server.impl.preferences.model; + +import com.sap.sse.common.settings.generic.AbstractGenericSerializableSettings; +import com.sap.sse.common.settings.generic.SettingsList; + +public class TrackedEventPreferences extends AbstractGenericSerializableSettings { + + private static final long serialVersionUID = -290209497308646446L; + + // TODO: setting preference title + public static final String PREF_NAME = SailingPreferences.TRACKED_EVENTS_PREFERENCES; + + private transient SettingsList trackedEvents; + + public TrackedEventPreferences() { + trackedEvents = new SettingsList<>("trackedEvents", this, () -> new TrackedEventPreference()); + } + + @Override + protected void addChildSettings() { + // We do not create the Setting instances here, because access to the RacingEventService would not be given. + // Doing this, Java/GWT Serialization isn't working anymore. Because the preferences are only serialized as JSON + // in the backend an transferred as DTO to the frontend, this isn't a problem. Due to usage of BoatClass and + // Competitor domain objects, it wouldn't be GWT compatible anyway. + // The usage of Java Serialization isn't planned by now, either. + } + + public Iterable getTrackedEvents() { + return trackedEvents.getValues(); + } + + public void setTrackedEvents(Iterable trackedEvents) { + this.trackedEvents.setValues(trackedEvents); + } +} From 520e62c35a50d70c49c5f9fa83d42eb7b10a6406 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Mon, 24 Jun 2019 12:52:17 +0200 Subject: [PATCH 02/69] added baseURl to TrackedEventPreference + changed type of trackedElementId to String to allow more versatile storing of tracked element UUIDs --- .../model/TrackedEventPreference.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java index 47179ecb43f..86fab7054dd 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java @@ -4,6 +4,7 @@ import java.util.UUID; import com.sap.sse.common.settings.generic.AbstractGenericSerializableSettings; import com.sap.sse.common.settings.generic.BooleanSetting; +import com.sap.sse.common.settings.generic.StringSetting; import com.sap.sse.common.settings.generic.UUIDSetting; public class TrackedEventPreference extends AbstractGenericSerializableSettings { @@ -12,14 +13,16 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings private transient UUIDSetting uuid; private transient UUIDSetting eventId; private transient UUIDSetting regattaId; - private transient UUIDSetting trackedElementId; + private transient StringSetting trackedElementId; + private transient StringSetting baseUrl; private transient BooleanSetting isArchived; public TrackedEventPreference() { uuid = new UUIDSetting("uuid", this); eventId = new UUIDSetting("eventId", this); regattaId = new UUIDSetting("regattaId", this); - trackedElementId = new UUIDSetting("trackedElementId", this); + trackedElementId = new StringSetting("trackedElementId", this); + baseUrl = new StringSetting("baseUrl", this); isArchived = new BooleanSetting("isArchived", this); } @@ -30,6 +33,7 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings eventId.setValue(other.getEventId()); regattaId.setValue(other.getRegattaId()); trackedElementId.setValue(other.getTrackedElementId()); + baseUrl.setValue(other.getBaseUrl()); isArchived.setValue(other.getIsArchived()); } @@ -40,15 +44,18 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings eventId.setValue(other.getEventId()); regattaId.setValue(other.getRegattaId()); trackedElementId.setValue(other.getTrackedElementId()); + baseUrl.setValue(other.getBaseUrl()); this.isArchived.setValue(isArchived); } - public TrackedEventPreference(UUID uuid, UUID eventId, UUID regattaId, UUID trackedElementId, boolean isArchived) { + public TrackedEventPreference(UUID uuid, UUID eventId, UUID regattaId, String trackedElementId, String baseUrl, + boolean isArchived) { this(); this.uuid.setValue(uuid); this.eventId.setValue(eventId); this.regattaId.setValue(regattaId); this.trackedElementId.setValue(trackedElementId); + this.baseUrl.setValue(baseUrl); this.isArchived.setValue(isArchived); } @@ -73,10 +80,14 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings return regattaId.getValue(); } - public UUID getTrackedElementId() { + public String getTrackedElementId() { return trackedElementId.getValue(); } + public String getBaseUrl() { + return baseUrl.getValue(); + } + public boolean getIsArchived() { return isArchived.getValue(); } From 817b5d814f4c4bee05e9c8d82837ba43dd19e117 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Mon, 24 Jun 2019 13:13:01 +0200 Subject: [PATCH 03/69] adjusted TrackedEventPreference --- .../preferences/model/TrackedElementType.java | 5 ++ .../model/TrackedElementWithDeviceId.java | 67 +++++++++++++++++++ .../model/TrackedEventPreference.java | 30 ++++----- 3 files changed, 84 insertions(+), 18 deletions(-) create mode 100644 java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedElementType.java create mode 100644 java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedElementWithDeviceId.java diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedElementType.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedElementType.java new file mode 100644 index 00000000000..06c2aabab53 --- /dev/null +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedElementType.java @@ -0,0 +1,5 @@ +package com.sap.sailing.server.impl.preferences.model; + +public enum TrackedElementType { + Boat, Competitor, Mark; +} diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedElementWithDeviceId.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedElementWithDeviceId.java new file mode 100644 index 00000000000..0700cc75623 --- /dev/null +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedElementWithDeviceId.java @@ -0,0 +1,67 @@ +package com.sap.sailing.server.impl.preferences.model; + +import java.util.UUID; + +import com.sap.sse.common.settings.generic.AbstractGenericSerializableSettings; +import com.sap.sse.common.settings.generic.StringSetting; +import com.sap.sse.common.settings.generic.UUIDSetting; + +public class TrackedElementWithDeviceId extends AbstractGenericSerializableSettings { + + private static final long serialVersionUID = 234711768869820003L; + + private transient StringSetting deviceId; + private transient UUIDSetting trackedCompetitorId; + private transient UUIDSetting trackedBoatId; + private transient UUIDSetting trackedMarkId; + + public TrackedElementWithDeviceId() { + deviceId = new StringSetting("deviceId", this); + trackedCompetitorId = new UUIDSetting("trackedCompetitorId", this); + trackedBoatId = new UUIDSetting("trackedBoatId", this); + trackedMarkId = new UUIDSetting("trackedMarkId", this); + } + + /** copy constructor */ + public TrackedElementWithDeviceId(TrackedElementWithDeviceId other) { + this(); + this.deviceId.setValue(other.getDeviceId()); + this.trackedBoatId.setValue(other.getTrackedBoatId()); + this.trackedCompetitorId.setValue(other.getTrackedCompetitorId()); + this.trackedMarkId.setValue(other.getTrackedMarkId()); + } + + public TrackedElementWithDeviceId(String deviceId, UUID trackedBoatId, UUID trackedCompetitorId, + UUID trackedMarkId) { + this(); + this.deviceId.setValue(deviceId); + this.trackedBoatId.setValue(trackedBoatId); + this.trackedCompetitorId.setValue(trackedCompetitorId); + this.trackedMarkId.setValue(trackedMarkId); + } + + @Override + protected void addChildSettings() { + // We do not create the Setting instances here, because access to the RacingEventService would not be given. + // Doing this, Java/GWT Serialization isn't working anymore. Because the preferences are only serialized as JSON + // in the backend an transferred as DTO to the frontend, this isn't a problem. Due to usage of BoatClass and + // Competitor domain objects, it wouldn't be GWT compatible anyway. + // The usage of Java Serialization isn't planned by now, either. + } + + public String getDeviceId() { + return deviceId.getValue(); + } + + public UUID getTrackedBoatId() { + return trackedBoatId.getValue(); + } + + public UUID getTrackedCompetitorId() { + return trackedCompetitorId.getValue(); + } + + public UUID getTrackedMarkId() { + return trackedMarkId.getValue(); + } +} diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java index 86fab7054dd..a47010f7cf6 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java @@ -4,24 +4,25 @@ import java.util.UUID; import com.sap.sse.common.settings.generic.AbstractGenericSerializableSettings; import com.sap.sse.common.settings.generic.BooleanSetting; +import com.sap.sse.common.settings.generic.SettingsList; import com.sap.sse.common.settings.generic.StringSetting; import com.sap.sse.common.settings.generic.UUIDSetting; public class TrackedEventPreference extends AbstractGenericSerializableSettings { private static final long serialVersionUID = 234711768869820003L; - private transient UUIDSetting uuid; private transient UUIDSetting eventId; private transient UUIDSetting regattaId; - private transient StringSetting trackedElementId; private transient StringSetting baseUrl; private transient BooleanSetting isArchived; + private transient SettingsList trackedElements; + public TrackedEventPreference() { - uuid = new UUIDSetting("uuid", this); eventId = new UUIDSetting("eventId", this); regattaId = new UUIDSetting("regattaId", this); - trackedElementId = new StringSetting("trackedElementId", this); + trackedElements = new SettingsList("trackedElements", this, + () -> new TrackedElementWithDeviceId()); baseUrl = new StringSetting("baseUrl", this); isArchived = new BooleanSetting("isArchived", this); } @@ -29,10 +30,9 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings /** copy constructor */ public TrackedEventPreference(TrackedEventPreference other) { this(); - uuid.setValue(other.getUuid()); eventId.setValue(other.getEventId()); regattaId.setValue(other.getRegattaId()); - trackedElementId.setValue(other.getTrackedElementId()); + trackedElements.setValues(other.getTrackedElements()); baseUrl.setValue(other.getBaseUrl()); isArchived.setValue(other.getIsArchived()); } @@ -40,21 +40,19 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings /** copy constructor with new archived state */ public TrackedEventPreference(TrackedEventPreference other, boolean isArchived) { this(); - uuid.setValue(other.getUuid()); eventId.setValue(other.getEventId()); regattaId.setValue(other.getRegattaId()); - trackedElementId.setValue(other.getTrackedElementId()); + trackedElements.setValues(other.getTrackedElements()); baseUrl.setValue(other.getBaseUrl()); this.isArchived.setValue(isArchived); } - public TrackedEventPreference(UUID uuid, UUID eventId, UUID regattaId, String trackedElementId, String baseUrl, - boolean isArchived) { + public TrackedEventPreference(UUID eventId, UUID regattaId, Iterable trackedElements, + String baseUrl, boolean isArchived) { this(); - this.uuid.setValue(uuid); this.eventId.setValue(eventId); this.regattaId.setValue(regattaId); - this.trackedElementId.setValue(trackedElementId); + this.trackedElements.setValues(trackedElements); this.baseUrl.setValue(baseUrl); this.isArchived.setValue(isArchived); } @@ -68,10 +66,6 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings // The usage of Java Serialization isn't planned by now, either. } - public UUID getUuid() { - return uuid.getValue(); - } - public UUID getEventId() { return eventId.getValue(); } @@ -80,8 +74,8 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings return regattaId.getValue(); } - public String getTrackedElementId() { - return trackedElementId.getValue(); + public Iterable getTrackedElements() { + return trackedElements.getValues(); } public String getBaseUrl() { From 7c80363c9a9f236d1041b3eb1a49ee880df635f4 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Mon, 24 Jun 2019 13:37:40 +0200 Subject: [PATCH 04/69] added initial version of TrackedEventsResource --- .../jaxrs/api/TrackedEventsResource.java | 170 ++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java new file mode 100644 index 00000000000..0984556576d --- /dev/null +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -0,0 +1,170 @@ +package com.sap.sailing.server.gateway.jaxrs.api; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.UUID; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; +import javax.ws.rs.core.Response.Status; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.JSONValue; +import org.json.simple.parser.ParseException; + +import com.sap.sailing.domain.base.Event; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; +import com.sap.sailing.server.gateway.deserialization.impl.Helpers; +import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource; +import com.sap.sailing.server.impl.preferences.model.SailingPreferences; +import com.sap.sailing.server.impl.preferences.model.TrackedElementWithDeviceId; +import com.sap.sailing.server.impl.preferences.model.TrackedEventPreference; +import com.sap.sailing.server.impl.preferences.model.TrackedEventPreferences; +import com.sap.sse.security.shared.OwnershipAnnotation; +import com.sap.sse.security.shared.impl.User; + +@Path("/v1/events/trackedevents/") +public class TrackedEventsResource extends AbstractSailingServerResource { + + private static final String KEY_EVENT_ID = "eventId"; + private static final String KEY_EVENT_IS_ARCHIVED = "isArchived"; + private static final String KEY_EVENT_NAME = "name"; + private static final String KEY_EVENT_START = "start"; + private static final String KEY_EVENT_AND = "end"; + private static final String KEY_EVENT_REGISTERED_DEVICE_IDS = "registeredDeviceIds"; + private static final String KEY_EVENT_BASE_URL = "url"; + private static final String KEY_EVENT_IS_OWNER = "isOwner"; + private static final String KEY_TRACKED_ELEMENT_ID = "deviceId"; + private static final String KEY_TRACKED_ELEMENT_COMPETITOR_ID = "competitorId"; + private static final String KEY_TRACKED_ELEMENT_BOAT_ID = "boatId"; + private static final String KEY_TRACKED_ELEMENT_MARK_ID = "markId"; + + @GET + @Produces("application/json;charset=UTF-8") + public Response getTrackedEvents(@QueryParam(KEY_EVENT_IS_ARCHIVED) String isArchived) { + + final User currentUser = getSecurityService().getCurrentUser(); + final ResponseBuilder builder; + + // check if user logged in + // TODO: handle requests for anonymous users + if (currentUser != null) { + + final TrackedEventPreferences prefs = getSecurityService().getPreferenceObject(currentUser.getName(), + SailingPreferences.TRACKED_EVENTS_PREFERENCES); + + final JSONArray result = new JSONArray(); + + final boolean showArchived = Boolean.parseBoolean(isArchived); + if (prefs != null) { + for (final TrackedEventPreference pref : prefs.getTrackedEvents()) { + + if (!showArchived && pref.getIsArchived()) { + // skip, if event is archived and should be filtered out + continue; + } + + final Event event = getService().getEvent(pref.getEventId()); + final OwnershipAnnotation ownership = getSecurityService().getOwnership(event.getIdentifier()); + final boolean isOwner = currentUser == null ? false + : currentUser.equals(ownership.getAnnotation().getUserOwner()); + + final JSONObject jsonEvent = new JSONObject(); + jsonEvent.put(KEY_EVENT_ID, event.getId().toString()); + jsonEvent.put(KEY_EVENT_NAME, event.getName()); + jsonEvent.put(KEY_EVENT_START, event.getStartDate().toString()); + jsonEvent.put(KEY_EVENT_AND, event.getEndDate().toString()); + + final JSONArray deviceIdsWithTrackedElementJson = new JSONArray(); + + for(TrackedElementWithDeviceId trackedElement : pref.getTrackedElements()) { + JSONObject trackedElementJson = new JSONObject(); + trackedElementJson.put(KEY_TRACKED_ELEMENT_ID, trackedElement.getDeviceId()); + if(trackedElement.getTrackedCompetitorId() != null) { + trackedElementJson.put(KEY_TRACKED_ELEMENT_COMPETITOR_ID, trackedElement.getTrackedCompetitorId().toString()); + } else if (trackedElement.getTrackedBoatId() != null) { + trackedElementJson.put(KEY_TRACKED_ELEMENT_BOAT_ID, + trackedElement.getTrackedBoatId().toString()); + } + else if (trackedElement.getTrackedMarkId() != null) { + trackedElementJson.put(KEY_TRACKED_ELEMENT_MARK_ID, + trackedElement.getTrackedMarkId().toString()); + } + } + + jsonEvent.put(KEY_EVENT_REGISTERED_DEVICE_IDS, deviceIdsWithTrackedElementJson); + // jsonEvent.put("imageUrl", event.getImages().) + jsonEvent.put(KEY_EVENT_BASE_URL, pref.getBaseUrl()); + jsonEvent.put(KEY_EVENT_IS_ARCHIVED, pref.getIsArchived()); + jsonEvent.put(KEY_EVENT_IS_OWNER, isOwner); + result.add(jsonEvent); + } + } + String json = result.toJSONString(); + builder = Response.ok(json).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8"); + } else { + builder = Response.status(Status.UNAUTHORIZED); + } + return builder.build(); + } + + @POST + @Consumes(MediaType.APPLICATION_JSON) + public Response updateTrackedEvents(String jsonBody) { + ResponseBuilder responseBuilder; + final User currentUser = getSecurityService().getCurrentUser(); + + if (currentUser != null) { + + try { + final Object requestBody = JSONValue.parseWithException(jsonBody); + final JSONObject requestObject = Helpers.toJSONObjectSafe(requestBody); + final String eventId = (String) requestObject.get(KEY_EVENT_ID); + final Boolean archived = (Boolean) requestObject.get(KEY_EVENT_IS_ARCHIVED); + try { + final UUID uuid = UUID.fromString(eventId); + final boolean isArchived = archived; + + TrackedEventPreferences prefs = getSecurityService().getPreferenceObject(currentUser.getName(), + SailingPreferences.TRACKED_EVENTS_PREFERENCES); + + if (prefs == null) { + prefs = new TrackedEventPreferences(); + } + + Collection prefsNew = new ArrayList<>(); + Iterator it = prefs.getTrackedEvents().iterator(); + while (it.hasNext()) { + final TrackedEventPreference pref = it.next(); + if (pref.getEventId().equals(uuid)) { + prefsNew.add(new TrackedEventPreference(pref, isArchived)); + } else { + prefsNew.add(pref); + } + } + + getSecurityService().setPreferenceObject(currentUser.getName(), + SailingPreferences.TRACKED_EVENTS_PREFERENCES, prefsNew); + responseBuilder = Response.status(Status.ACCEPTED); + } catch (IllegalArgumentException | ClassCastException e) { + responseBuilder = Response.status(Status.BAD_REQUEST) + .entity("Invalid or missing attributes in JSON body."); + } + } catch (ParseException | JsonDeserializationException e) { + responseBuilder = Response.status(Status.BAD_REQUEST).entity("Invalid JSON body in request."); + } + } else { + responseBuilder = Response.status(Status.UNAUTHORIZED); + } + return responseBuilder.build(); + } +} From 90841acee4d86df1bc73445b1d7388b0a03418bb Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Mon, 24 Jun 2019 15:17:38 +0200 Subject: [PATCH 05/69] Bug 4960: adjusted naming in TrackedEventsResource --- .../server/gateway/jaxrs/api/TrackedEventsResource.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index 0984556576d..72fecf381d6 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -40,10 +40,10 @@ public class TrackedEventsResource extends AbstractSailingServerResource { private static final String KEY_EVENT_NAME = "name"; private static final String KEY_EVENT_START = "start"; private static final String KEY_EVENT_AND = "end"; - private static final String KEY_EVENT_REGISTERED_DEVICE_IDS = "registeredDeviceIds"; + private static final String KEY_EVENT_TRACKED_ELEMENTS = "trackedElements"; private static final String KEY_EVENT_BASE_URL = "url"; private static final String KEY_EVENT_IS_OWNER = "isOwner"; - private static final String KEY_TRACKED_ELEMENT_ID = "deviceId"; + private static final String KEY_TRACKED_ELEMENT_DEVICE_ID = "deviceId"; private static final String KEY_TRACKED_ELEMENT_COMPETITOR_ID = "competitorId"; private static final String KEY_TRACKED_ELEMENT_BOAT_ID = "boatId"; private static final String KEY_TRACKED_ELEMENT_MARK_ID = "markId"; @@ -88,7 +88,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { for(TrackedElementWithDeviceId trackedElement : pref.getTrackedElements()) { JSONObject trackedElementJson = new JSONObject(); - trackedElementJson.put(KEY_TRACKED_ELEMENT_ID, trackedElement.getDeviceId()); + trackedElementJson.put(KEY_TRACKED_ELEMENT_DEVICE_ID, trackedElement.getDeviceId()); if(trackedElement.getTrackedCompetitorId() != null) { trackedElementJson.put(KEY_TRACKED_ELEMENT_COMPETITOR_ID, trackedElement.getTrackedCompetitorId().toString()); } else if (trackedElement.getTrackedBoatId() != null) { @@ -101,7 +101,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { } } - jsonEvent.put(KEY_EVENT_REGISTERED_DEVICE_IDS, deviceIdsWithTrackedElementJson); + jsonEvent.put(KEY_EVENT_TRACKED_ELEMENTS, deviceIdsWithTrackedElementJson); // jsonEvent.put("imageUrl", event.getImages().) jsonEvent.put(KEY_EVENT_BASE_URL, pref.getBaseUrl()); jsonEvent.put(KEY_EVENT_IS_ARCHIVED, pref.getIsArchived()); From 345fecf402094962eacff35eaee16dd2e5977afb Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Mon, 24 Jun 2019 15:26:11 +0200 Subject: [PATCH 06/69] added TrackedEventsResource to RestApiApplication --- .../sap/sailing/server/gateway/jaxrs/api/RestApiApplication.java | 1 + 1 file changed, 1 insertion(+) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RestApiApplication.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RestApiApplication.java index 083cd0942be..66469183084 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RestApiApplication.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RestApiApplication.java @@ -35,6 +35,7 @@ public class RestApiApplication extends Application { classes.add(TagsResource.class); classes.add(UserGroupsResource.class); classes.add(StatusResource.class); + classes.add(TrackedEventsResource.class); // Exception Mappers classes.add(ShiroAuthorizationExceptionTo401ResponseMapper.class); From ac1ba531aa969fe5ac2a352f57a4a3338121d4e4 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 25 Jun 2019 14:06:51 +0200 Subject: [PATCH 07/69] Bug 4960: added wrapping for JSONArray when retrieving TrackedEventsResource --- .../server/gateway/jaxrs/api/TrackedEventsResource.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index 72fecf381d6..a06a7d26fb5 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -47,6 +47,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { private static final String KEY_TRACKED_ELEMENT_COMPETITOR_ID = "competitorId"; private static final String KEY_TRACKED_ELEMENT_BOAT_ID = "boatId"; private static final String KEY_TRACKED_ELEMENT_MARK_ID = "markId"; + private static final String KEY_TRACKED_EVENTS = "trackedEvents"; @GET @Produces("application/json;charset=UTF-8") @@ -109,7 +110,10 @@ public class TrackedEventsResource extends AbstractSailingServerResource { result.add(jsonEvent); } } - String json = result.toJSONString(); + + JSONObject resultEvents = new JSONObject(); + resultEvents.put(KEY_TRACKED_EVENTS, result); + String json = resultEvents.toJSONString(); builder = Response.ok(json).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8"); } else { builder = Response.status(Status.UNAUTHORIZED); From 0c237b85722fd3907de1184883e20c18e4e8f30a Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 25 Jun 2019 14:08:47 +0200 Subject: [PATCH 08/69] added simple Selenium Test for TrackedEventsResource --- .../selenium/api/event/TrackedEventsApi.java | 123 ++++++++++++++++++ .../test/TrackedEventsResourceApiTest.java | 33 +++++ .../jaxrs/api/TrackedEventsResource.java | 12 +- 3 files changed, 162 insertions(+), 6 deletions(-) create mode 100644 java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java create mode 100644 java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java new file mode 100644 index 00000000000..6e951923117 --- /dev/null +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java @@ -0,0 +1,123 @@ +package com.sap.sailing.selenium.api.event; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import com.sap.sailing.selenium.api.core.ApiContext; +import com.sap.sailing.selenium.api.core.JsonWrapper; + +public class TrackedEventsApi { + + private static final String TRACKED_EVENTS_URL = "/api/v1/events/trackedevents/"; + private static final String KEY_TRACKED_EVENTS = "trackedEvents"; + + private static final String KEY_EVENT_ID = "eventId"; + private static final String KEY_EVENT_IS_ARCHIVED = "isArchived"; + private static final String KEY_EVENT_NAME = "name"; + private static final String KEY_EVENT_START = "start"; + private static final String KEY_EVENT_END = "end"; + private static final String KEY_EVENT_BASE_URL = "url"; + private static final String KEY_EVENT_IS_OWNER = "isOwner"; + + private static final String KEY_EVENT_TRACKED_ELEMENTS = "trackedElements"; + + private static final String KEY_TRACKED_ELEMENT_DEVICE_ID = "deviceId"; + private static final String KEY_TRACKED_ELEMENT_COMPETITOR_ID = "competitorId"; + private static final String KEY_TRACKED_ELEMENT_BOAT_ID = "boatId"; + private static final String KEY_TRACKED_ELEMENT_MARK_ID = "markId"; + + public TrackedEvents getTrackedEvents(ApiContext ctx, boolean isArchived) { + final Map queryParams = new HashMap<>(); + queryParams.put(KEY_EVENT_IS_ARCHIVED, Boolean.toString(isArchived)); + return new TrackedEvents(ctx.get(TRACKED_EVENTS_URL, queryParams)); + } + + public class TrackedElement extends JsonWrapper { + public TrackedElement(JSONObject json) { + super(json); + } + + public String getCompetitorId() { + return get(KEY_TRACKED_ELEMENT_COMPETITOR_ID); + } + + public String getBoatId() { + return get(KEY_TRACKED_ELEMENT_BOAT_ID); + } + + public String getMarkId() { + return get(KEY_TRACKED_ELEMENT_MARK_ID); + } + + public String getDeviceId() { + return get(KEY_TRACKED_ELEMENT_DEVICE_ID); + } + } + + public class TrackedEvents extends JsonWrapper { + public TrackedEvents(JSONObject json) { + super(json); + } + + public Iterable getEvents() { + final Collection events = new ArrayList<>(); + JSONArray array = get(KEY_TRACKED_EVENTS); + for (Object json : array) { + events.add((TrackedEvent) json); + } + return events; + } + } + + public class TrackedEvent extends JsonWrapper { + + public TrackedEvent(JSONObject json) { + super(json); + } + + public String getEventId() { + return get(KEY_EVENT_ID); + } + + public String getEventName() { + return get(KEY_EVENT_NAME); + } + + public String getEventStart() { + return get(KEY_EVENT_START); + } + + public String getEventEnd() { + return get(KEY_EVENT_END); + } + + public String getEventBaseUrl() { + return get(KEY_EVENT_BASE_URL); + } + + public boolean isArchived() { + return get(KEY_EVENT_IS_ARCHIVED); + } + + public boolean isOwner() { + return get(KEY_EVENT_IS_OWNER); + } + + public Iterable getTrackedElements() { + JSONArray array = get(KEY_EVENT_TRACKED_ELEMENTS); + Collection col = new ArrayList<>(); + if (array != null) { + for (Object w : array) { + col.add((TrackedElement) w); + } + } + return col; + } + } + +} diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java new file mode 100644 index 00000000000..6b507678500 --- /dev/null +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java @@ -0,0 +1,33 @@ +package com.sap.sailing.selenium.api.test; + +import static com.sap.sailing.selenium.api.core.ApiContext.SERVER_CONTEXT; +import static com.sap.sailing.selenium.api.core.ApiContext.createAdminApiContext; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.sap.sailing.selenium.api.core.ApiContext; +import com.sap.sailing.selenium.api.event.TrackedEventsApi; +import com.sap.sailing.selenium.api.event.TrackedEventsApi.TrackedEvents; +import com.sap.sailing.selenium.test.AbstractSeleniumTest; +import com.sap.sse.common.Util; + +public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { + + private final TrackedEventsApi trackedEventsApi = new TrackedEventsApi(); + + @Before + public void setUp() { + clearState(getContextRoot()); + } + + @Test + public void testGetTrackedEventsEmpty() { + final ApiContext adminCtx = createAdminApiContext(getContextRoot(), SERVER_CONTEXT); + final TrackedEvents trackedEvents = trackedEventsApi.getTrackedEvents(adminCtx, true); + Assert.assertNotNull(trackedEvents); + Assert.assertTrue(Util.isEmpty(trackedEvents.getEvents())); + } + +} diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index a06a7d26fb5..c29fa111b11 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -88,7 +88,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { final JSONArray deviceIdsWithTrackedElementJson = new JSONArray(); for(TrackedElementWithDeviceId trackedElement : pref.getTrackedElements()) { - JSONObject trackedElementJson = new JSONObject(); + final JSONObject trackedElementJson = new JSONObject(); trackedElementJson.put(KEY_TRACKED_ELEMENT_DEVICE_ID, trackedElement.getDeviceId()); if(trackedElement.getTrackedCompetitorId() != null) { trackedElementJson.put(KEY_TRACKED_ELEMENT_COMPETITOR_ID, trackedElement.getTrackedCompetitorId().toString()); @@ -111,10 +111,10 @@ public class TrackedEventsResource extends AbstractSailingServerResource { } } - JSONObject resultEvents = new JSONObject(); + final JSONObject resultEvents = new JSONObject(); resultEvents.put(KEY_TRACKED_EVENTS, result); - String json = resultEvents.toJSONString(); - builder = Response.ok(json).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8"); + final String jsonString = resultEvents.toJSONString(); + builder = Response.ok(jsonString).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8"); } else { builder = Response.status(Status.UNAUTHORIZED); } @@ -145,8 +145,8 @@ public class TrackedEventsResource extends AbstractSailingServerResource { prefs = new TrackedEventPreferences(); } - Collection prefsNew = new ArrayList<>(); - Iterator it = prefs.getTrackedEvents().iterator(); + final Collection prefsNew = new ArrayList<>(); + final Iterator it = prefs.getTrackedEvents().iterator(); while (it.hasNext()) { final TrackedEventPreference pref = it.next(); if (pref.getEventId().equals(uuid)) { From 9e2ecb0be0883831a5907653f29e646a3a1f48b3 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 25 Jun 2019 14:42:19 +0200 Subject: [PATCH 09/69] BUG 4960: added copy constructor with additional tracked event --- .../model/TrackedEventPreference.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java index a47010f7cf6..8a0b2144410 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java @@ -1,7 +1,10 @@ package com.sap.sailing.server.impl.preferences.model; +import java.util.ArrayList; +import java.util.Collection; import java.util.UUID; +import com.sap.sse.common.Util; import com.sap.sse.common.settings.generic.AbstractGenericSerializableSettings; import com.sap.sse.common.settings.generic.BooleanSetting; import com.sap.sse.common.settings.generic.SettingsList; @@ -47,6 +50,19 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings this.isArchived.setValue(isArchived); } + /** copy constructor with additional tracked event */ + public TrackedEventPreference(TrackedEventPreference other, TrackedElementWithDeviceId trackedElement) { + this(); + eventId.setValue(other.getEventId()); + regattaId.setValue(other.getRegattaId()); + final Collection trackedElements = new ArrayList<>(); + Util.addAll(other.getTrackedElements(), trackedElements); + trackedElements.add(trackedElement); + this.trackedElements.setValues(trackedElements); + baseUrl.setValue(other.getBaseUrl()); + this.isArchived.setValue(other.getIsArchived()); + } + public TrackedEventPreference(UUID eventId, UUID regattaId, Iterable trackedElements, String baseUrl, boolean isArchived) { this(); From 3645a1d4a01c95d072d17becbca7772e932546d8 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 25 Jun 2019 14:42:45 +0200 Subject: [PATCH 10/69] Bug 4960: added PUT end point for TrackedEventsResource --- .../jaxrs/api/TrackedEventsResource.java | 128 +++++++++++++++++- 1 file changed, 123 insertions(+), 5 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index c29fa111b11..d33d28c70f7 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -1,6 +1,7 @@ package com.sap.sailing.server.gateway.jaxrs.api; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.UUID; @@ -8,6 +9,7 @@ import java.util.UUID; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.POST; +import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; @@ -35,6 +37,7 @@ import com.sap.sse.security.shared.impl.User; @Path("/v1/events/trackedevents/") public class TrackedEventsResource extends AbstractSailingServerResource { + private static final String KEY_REGATTA_ID = "regattaId"; private static final String KEY_EVENT_ID = "eventId"; private static final String KEY_EVENT_IS_ARCHIVED = "isArchived"; private static final String KEY_EVENT_NAME = "name"; @@ -87,16 +90,16 @@ public class TrackedEventsResource extends AbstractSailingServerResource { final JSONArray deviceIdsWithTrackedElementJson = new JSONArray(); - for(TrackedElementWithDeviceId trackedElement : pref.getTrackedElements()) { + for (TrackedElementWithDeviceId trackedElement : pref.getTrackedElements()) { final JSONObject trackedElementJson = new JSONObject(); trackedElementJson.put(KEY_TRACKED_ELEMENT_DEVICE_ID, trackedElement.getDeviceId()); - if(trackedElement.getTrackedCompetitorId() != null) { - trackedElementJson.put(KEY_TRACKED_ELEMENT_COMPETITOR_ID, trackedElement.getTrackedCompetitorId().toString()); + if (trackedElement.getTrackedCompetitorId() != null) { + trackedElementJson.put(KEY_TRACKED_ELEMENT_COMPETITOR_ID, + trackedElement.getTrackedCompetitorId().toString()); } else if (trackedElement.getTrackedBoatId() != null) { trackedElementJson.put(KEY_TRACKED_ELEMENT_BOAT_ID, trackedElement.getTrackedBoatId().toString()); - } - else if (trackedElement.getTrackedMarkId() != null) { + } else if (trackedElement.getTrackedMarkId() != null) { trackedElementJson.put(KEY_TRACKED_ELEMENT_MARK_ID, trackedElement.getTrackedMarkId().toString()); } @@ -121,6 +124,121 @@ public class TrackedEventsResource extends AbstractSailingServerResource { return builder.build(); } + @PUT + @Consumes(MediaType.APPLICATION_JSON) + public Response addTrackedEvent(String jsonBody) { + ResponseBuilder responseBuilder = null; + final User currentUser = getSecurityService().getCurrentUser(); + + if (currentUser != null) { + + try { + final Object requestBody = JSONValue.parseWithException(jsonBody); + final JSONObject requestObject = Helpers.toJSONObjectSafe(requestBody); + final String eventId = (String) requestObject.get(KEY_EVENT_ID); + final String regattaId = (String) requestObject.get(KEY_REGATTA_ID); + final Boolean archived = (Boolean) requestObject.get(KEY_EVENT_IS_ARCHIVED); + final String baseUrl = (String) requestObject.get(KEY_EVENT_BASE_URL); + try { + final UUID uuidEvent = UUID.fromString(eventId); + final UUID uuidRegatta = UUID.fromString(regattaId); + final boolean isArchived = archived; + + TrackedEventPreferences prefs = getSecurityService().getPreferenceObject(currentUser.getName(), + SailingPreferences.TRACKED_EVENTS_PREFERENCES); + + if (prefs == null) { + prefs = new TrackedEventPreferences(); + } + + final String deviceId = (String) requestObject.get(KEY_TRACKED_ELEMENT_DEVICE_ID); + final String competitorIdStr = (String) requestObject.get(KEY_TRACKED_ELEMENT_COMPETITOR_ID); + final String boatIdStr = (String) requestObject.get(KEY_TRACKED_ELEMENT_BOAT_ID); + final String markIdStr = (String) requestObject.get(KEY_TRACKED_ELEMENT_MARK_ID); + + // cannot be final without either violating single point of return or multiple assignments in + // try/catch + UUID competitorId; + UUID boatId; + UUID markId; + if (competitorIdStr != null && !competitorIdStr.isEmpty()) { + try { + competitorId = UUID.fromString(competitorIdStr); + } catch (IllegalArgumentException e) { + responseBuilder = Response.status(Status.BAD_REQUEST) + .entity("Invalid JSON body in request."); + competitorId = null; + } + boatId = null; + markId = null; + } else if (boatIdStr != null && !boatIdStr.isEmpty()) { + try { + boatId = UUID.fromString(competitorIdStr); + } catch (IllegalArgumentException e) { + responseBuilder = Response.status(Status.BAD_REQUEST) + .entity("Invalid JSON body in request."); + boatId = null; + } + competitorId = null; + markId = null; + } else if (markIdStr != null && !markIdStr.isEmpty()) { + try { + markId = UUID.fromString(competitorIdStr); + } catch (IllegalArgumentException e) { + responseBuilder = Response.status(Status.BAD_REQUEST) + .entity("Invalid JSON body in request."); + markId = null; + } + boatId = null; + competitorId = null; + } else { + responseBuilder = Response.status(Status.BAD_REQUEST).entity("Invalid JSON body in request."); + markId = boatId = competitorId = null; + } + + if (boatId != null || markId != null || competitorId != null) { + final TrackedElementWithDeviceId newPrefElem = new TrackedElementWithDeviceId(deviceId, boatId, + competitorId, markId); + + final Collection prefsNew = new ArrayList<>(); + final Iterator it = prefs.getTrackedEvents().iterator(); + + boolean eventContained = false; + while (it.hasNext()) { + final TrackedEventPreference pref = it.next(); + if (pref.getEventId().equals(uuidEvent) && pref.getRegattaId().equals(uuidRegatta)) { + prefsNew.add(new TrackedEventPreference(pref, newPrefElem)); + eventContained = true; + } else { + prefsNew.add(pref); + } + } + + if (!eventContained) { + final TrackedEventPreference newPreference = new TrackedEventPreference(uuidEvent, + uuidRegatta, Arrays.asList(newPrefElem), baseUrl, isArchived); + prefsNew.add(newPreference); + } + getSecurityService().setPreferenceObject(currentUser.getName(), + SailingPreferences.TRACKED_EVENTS_PREFERENCES, prefsNew); + responseBuilder = Response.status(Status.ACCEPTED); + } else { + // TODO return + } + + } catch (IllegalArgumentException | ClassCastException e) { + responseBuilder = Response.status(Status.BAD_REQUEST) + .entity("Invalid or missing attributes in JSON body."); + } + } catch (ParseException | JsonDeserializationException e) { + responseBuilder = Response.status(Status.BAD_REQUEST).entity("Invalid JSON body in request."); + } + } else { + responseBuilder = Response.status(Status.UNAUTHORIZED); + } + return responseBuilder.build(); + } + @POST @Consumes(MediaType.APPLICATION_JSON) public Response updateTrackedEvents(String jsonBody) { From 3caf3ec31dea615c6eaf7dde67baa50a93b2d1f7 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 25 Jun 2019 15:13:49 +0200 Subject: [PATCH 11/69] Bug 4960: adjusted put routine for creating elements in TrackedEventsResoure --- .../jaxrs/api/TrackedEventsResource.java | 154 ++++++++++-------- 1 file changed, 90 insertions(+), 64 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index d33d28c70f7..dcca55ba5b4 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -151,79 +151,105 @@ public class TrackedEventsResource extends AbstractSailingServerResource { prefs = new TrackedEventPreferences(); } - final String deviceId = (String) requestObject.get(KEY_TRACKED_ELEMENT_DEVICE_ID); - final String competitorIdStr = (String) requestObject.get(KEY_TRACKED_ELEMENT_COMPETITOR_ID); - final String boatIdStr = (String) requestObject.get(KEY_TRACKED_ELEMENT_BOAT_ID); - final String markIdStr = (String) requestObject.get(KEY_TRACKED_ELEMENT_MARK_ID); + JSONArray trackedElementsJson = (JSONArray) requestObject.get(KEY_EVENT_TRACKED_ELEMENTS); - // cannot be final without either violating single point of return or multiple assignments in - // try/catch - UUID competitorId; - UUID boatId; - UUID markId; - if (competitorIdStr != null && !competitorIdStr.isEmpty()) { - try { - competitorId = UUID.fromString(competitorIdStr); - } catch (IllegalArgumentException e) { - responseBuilder = Response.status(Status.BAD_REQUEST) - .entity("Invalid JSON body in request."); - competitorId = null; - } - boatId = null; - markId = null; - } else if (boatIdStr != null && !boatIdStr.isEmpty()) { - try { - boatId = UUID.fromString(competitorIdStr); - } catch (IllegalArgumentException e) { - responseBuilder = Response.status(Status.BAD_REQUEST) - .entity("Invalid JSON body in request."); - boatId = null; - } - competitorId = null; - markId = null; - } else if (markIdStr != null && !markIdStr.isEmpty()) { - try { - markId = UUID.fromString(competitorIdStr); - } catch (IllegalArgumentException e) { - responseBuilder = Response.status(Status.BAD_REQUEST) - .entity("Invalid JSON body in request."); - markId = null; - } - boatId = null; - competitorId = null; + if (trackedElementsJson == null || trackedElementsJson.size() == 0) { + responseBuilder = Response.status(Status.BAD_REQUEST) + .entity("Invalid JSON body in request: Tracked element is missing."); + } else if (trackedElementsJson.size() > 1) { + responseBuilder = Response.status(Status.BAD_REQUEST).entity( + "Invalid JSON body in request: Too many tracked elements: Only updating one tracked element per call is allowed."); } else { - responseBuilder = Response.status(Status.BAD_REQUEST).entity("Invalid JSON body in request."); - markId = boatId = competitorId = null; - } + // tracked json elements array has exactly one child + final JSONObject jsonTrackedElement = (JSONObject) trackedElementsJson.get(0); - if (boatId != null || markId != null || competitorId != null) { - final TrackedElementWithDeviceId newPrefElem = new TrackedElementWithDeviceId(deviceId, boatId, - competitorId, markId); + if (jsonTrackedElement == null) { + responseBuilder = Response.status(Status.BAD_REQUEST) + .entity("Invalid JSON body in request: Tracked element is missing in array."); + } - final Collection prefsNew = new ArrayList<>(); - final Iterator it = prefs.getTrackedEvents().iterator(); + else { - boolean eventContained = false; - while (it.hasNext()) { - final TrackedEventPreference pref = it.next(); - if (pref.getEventId().equals(uuidEvent) && pref.getRegattaId().equals(uuidRegatta)) { - prefsNew.add(new TrackedEventPreference(pref, newPrefElem)); - eventContained = true; + final String deviceId = (String) jsonTrackedElement.get(KEY_TRACKED_ELEMENT_DEVICE_ID); + final String competitorIdStr = (String) jsonTrackedElement + .get(KEY_TRACKED_ELEMENT_COMPETITOR_ID); + final String boatIdStr = (String) jsonTrackedElement.get(KEY_TRACKED_ELEMENT_BOAT_ID); + final String markIdStr = (String) jsonTrackedElement.get(KEY_TRACKED_ELEMENT_MARK_ID); + + // cannot be final without either violating single point of return or multiple assignments + // in + // try/catch + UUID competitorId; + UUID boatId; + UUID markId; + if (competitorIdStr != null && !competitorIdStr.isEmpty()) { + try { + competitorId = UUID.fromString(competitorIdStr); + } catch (IllegalArgumentException e) { + responseBuilder = Response.status(Status.BAD_REQUEST) + .entity("Invalid JSON body in request."); + competitorId = null; + } + boatId = null; + markId = null; + } else if (boatIdStr != null && !boatIdStr.isEmpty()) { + try { + boatId = UUID.fromString(competitorIdStr); + } catch (IllegalArgumentException e) { + responseBuilder = Response.status(Status.BAD_REQUEST) + .entity("Invalid JSON body in request."); + boatId = null; + } + competitorId = null; + markId = null; + } else if (markIdStr != null && !markIdStr.isEmpty()) { + try { + markId = UUID.fromString(competitorIdStr); + } catch (IllegalArgumentException e) { + responseBuilder = Response.status(Status.BAD_REQUEST) + .entity("Invalid JSON body in request."); + markId = null; + } + boatId = null; + competitorId = null; } else { - prefsNew.add(pref); + responseBuilder = Response.status(Status.BAD_REQUEST) + .entity("Invalid JSON body in request."); + markId = boatId = competitorId = null; + } + + if (boatId != null || markId != null || competitorId != null) { + final TrackedElementWithDeviceId newPrefElem = new TrackedElementWithDeviceId(deviceId, + boatId, competitorId, markId); + + final Collection prefsNew = new ArrayList<>(); + final Iterator it = prefs.getTrackedEvents().iterator(); + + boolean eventContained = false; + while (it.hasNext()) { + final TrackedEventPreference pref = it.next(); + if (pref.getEventId().equals(uuidEvent) + && pref.getRegattaId().equals(uuidRegatta)) { + prefsNew.add(new TrackedEventPreference(pref, newPrefElem)); + eventContained = true; + } else { + prefsNew.add(pref); + } + } + + if (!eventContained) { + final TrackedEventPreference newPreference = new TrackedEventPreference(uuidEvent, + uuidRegatta, Arrays.asList(newPrefElem), baseUrl, isArchived); + prefsNew.add(newPreference); + } + getSecurityService().setPreferenceObject(currentUser.getName(), + SailingPreferences.TRACKED_EVENTS_PREFERENCES, prefsNew); + responseBuilder = Response.status(Status.ACCEPTED); + } else { + // no boatId, competitorId or markId were specified } } - if (!eventContained) { - final TrackedEventPreference newPreference = new TrackedEventPreference(uuidEvent, - uuidRegatta, Arrays.asList(newPrefElem), baseUrl, isArchived); - prefsNew.add(newPreference); - } - getSecurityService().setPreferenceObject(currentUser.getName(), - SailingPreferences.TRACKED_EVENTS_PREFERENCES, prefsNew); - responseBuilder = Response.status(Status.ACCEPTED); - } else { - // TODO return } } catch (IllegalArgumentException | ClassCastException e) { From 52c31f4cd80aeed65fbfd3706b08d8b327a3bc20 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 25 Jun 2019 15:18:31 +0200 Subject: [PATCH 12/69] Bug 4960: added JSONPreferenceConverter for TrackedEventPreferences --- .../src/com/sap/sailing/server/impl/Activator.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/Activator.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/Activator.java index 61841b312ae..49c82a475bb 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/Activator.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/Activator.java @@ -46,6 +46,7 @@ import com.sap.sailing.server.impl.preferences.model.BoatClassNotificationPrefer import com.sap.sailing.server.impl.preferences.model.CompetitorNotificationPreferences; import com.sap.sailing.server.impl.preferences.model.SailorProfilePreferences; import com.sap.sailing.server.impl.preferences.model.StoredDataMiningQueryPreferences; +import com.sap.sailing.server.impl.preferences.model.TrackedEventPreferences; import com.sap.sailing.server.interfaces.RacingEventService; import com.sap.sailing.server.notification.impl.SailingNotificationServiceImpl; import com.sap.sailing.server.security.SailingViewerRole; @@ -159,6 +160,9 @@ public class Activator implements BundleActivator { new GenericJSONPreferenceConverter<>( () -> new SailorProfilePreferences(racingEventService.getCompetitorAndBoatStore())), properties)); + properties.put(PreferenceConverter.KEY_PARAMETER_NAME, TrackedEventPreferences.PREF_NAME); + registrations.add(context.registerService(PreferenceConverter.class, + new GenericJSONPreferenceConverter<>(() -> new TrackedEventPreferences()), properties)); } public static BundleContext getContext() { From 35f102d50e7fbed2562375f71cd1c54debd6aefc Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 25 Jun 2019 17:14:47 +0200 Subject: [PATCH 13/69] Bug 4960: fixed conversion error in TrackedEventsResource --- .../jaxrs/api/TrackedEventsResource.java | 65 ++++++++++--------- .../model/TrackedEventPreference.java | 4 +- 2 files changed, 37 insertions(+), 32 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index dcca55ba5b4..1a4acaca618 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -77,40 +77,43 @@ public class TrackedEventsResource extends AbstractSailingServerResource { continue; } - final Event event = getService().getEvent(pref.getEventId()); - final OwnershipAnnotation ownership = getSecurityService().getOwnership(event.getIdentifier()); - final boolean isOwner = currentUser == null ? false - : currentUser.equals(ownership.getAnnotation().getUserOwner()); + final UUID eventId = pref.getEventId(); + final Event event = getService().getEvent(eventId); + if (event != null) { + final OwnershipAnnotation ownership = getSecurityService().getOwnership(event.getIdentifier()); + final boolean isOwner = currentUser == null ? false + : currentUser.equals(ownership.getAnnotation().getUserOwner()); - final JSONObject jsonEvent = new JSONObject(); - jsonEvent.put(KEY_EVENT_ID, event.getId().toString()); - jsonEvent.put(KEY_EVENT_NAME, event.getName()); - jsonEvent.put(KEY_EVENT_START, event.getStartDate().toString()); - jsonEvent.put(KEY_EVENT_AND, event.getEndDate().toString()); + final JSONObject jsonEvent = new JSONObject(); + jsonEvent.put(KEY_EVENT_ID, event.getId().toString()); + jsonEvent.put(KEY_EVENT_NAME, event.getName()); + jsonEvent.put(KEY_EVENT_START, event.getStartDate().toString()); + jsonEvent.put(KEY_EVENT_AND, event.getEndDate().toString()); - final JSONArray deviceIdsWithTrackedElementJson = new JSONArray(); + final JSONArray deviceIdsWithTrackedElementJson = new JSONArray(); - for (TrackedElementWithDeviceId trackedElement : pref.getTrackedElements()) { - final JSONObject trackedElementJson = new JSONObject(); - trackedElementJson.put(KEY_TRACKED_ELEMENT_DEVICE_ID, trackedElement.getDeviceId()); - if (trackedElement.getTrackedCompetitorId() != null) { - trackedElementJson.put(KEY_TRACKED_ELEMENT_COMPETITOR_ID, - trackedElement.getTrackedCompetitorId().toString()); - } else if (trackedElement.getTrackedBoatId() != null) { - trackedElementJson.put(KEY_TRACKED_ELEMENT_BOAT_ID, - trackedElement.getTrackedBoatId().toString()); - } else if (trackedElement.getTrackedMarkId() != null) { - trackedElementJson.put(KEY_TRACKED_ELEMENT_MARK_ID, - trackedElement.getTrackedMarkId().toString()); + for (TrackedElementWithDeviceId trackedElement : pref.getTrackedElements()) { + final JSONObject trackedElementJson = new JSONObject(); + trackedElementJson.put(KEY_TRACKED_ELEMENT_DEVICE_ID, trackedElement.getDeviceId()); + if (trackedElement.getTrackedCompetitorId() != null) { + trackedElementJson.put(KEY_TRACKED_ELEMENT_COMPETITOR_ID, + trackedElement.getTrackedCompetitorId().toString()); + } else if (trackedElement.getTrackedBoatId() != null) { + trackedElementJson.put(KEY_TRACKED_ELEMENT_BOAT_ID, + trackedElement.getTrackedBoatId().toString()); + } else if (trackedElement.getTrackedMarkId() != null) { + trackedElementJson.put(KEY_TRACKED_ELEMENT_MARK_ID, + trackedElement.getTrackedMarkId().toString()); + } } - } - jsonEvent.put(KEY_EVENT_TRACKED_ELEMENTS, deviceIdsWithTrackedElementJson); - // jsonEvent.put("imageUrl", event.getImages().) - jsonEvent.put(KEY_EVENT_BASE_URL, pref.getBaseUrl()); - jsonEvent.put(KEY_EVENT_IS_ARCHIVED, pref.getIsArchived()); - jsonEvent.put(KEY_EVENT_IS_OWNER, isOwner); - result.add(jsonEvent); + jsonEvent.put(KEY_EVENT_TRACKED_ELEMENTS, deviceIdsWithTrackedElementJson); + // jsonEvent.put("imageUrl", event.getImages().) + jsonEvent.put(KEY_EVENT_BASE_URL, pref.getBaseUrl()); + jsonEvent.put(KEY_EVENT_IS_ARCHIVED, pref.getIsArchived()); + jsonEvent.put(KEY_EVENT_IS_OWNER, isOwner); + result.add(jsonEvent); + } } } @@ -242,8 +245,10 @@ public class TrackedEventsResource extends AbstractSailingServerResource { uuidRegatta, Arrays.asList(newPrefElem), baseUrl, isArchived); prefsNew.add(newPreference); } + + prefs.setTrackedEvents(prefsNew); getSecurityService().setPreferenceObject(currentUser.getName(), - SailingPreferences.TRACKED_EVENTS_PREFERENCES, prefsNew); + SailingPreferences.TRACKED_EVENTS_PREFERENCES, prefs); responseBuilder = Response.status(Status.ACCEPTED); } else { // no boatId, competitorId or markId were specified diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java index 8a0b2144410..6bb9f64ef3e 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java @@ -1,7 +1,7 @@ package com.sap.sailing.server.impl.preferences.model; -import java.util.ArrayList; import java.util.Collection; +import java.util.HashSet; import java.util.UUID; import com.sap.sse.common.Util; @@ -55,7 +55,7 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings this(); eventId.setValue(other.getEventId()); regattaId.setValue(other.getRegattaId()); - final Collection trackedElements = new ArrayList<>(); + final Collection trackedElements = new HashSet<>(); Util.addAll(other.getTrackedElements(), trackedElements); trackedElements.add(trackedElement); this.trackedElements.setValues(trackedElements); From 9ff24167fe46f010545f5ec4f05bf4b61dcaa8ff Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 25 Jun 2019 17:15:23 +0200 Subject: [PATCH 14/69] Bug 4960: added method to update a tracked event to TrackedEventsApi for later testing --- .../selenium/api/event/TrackedEventsApi.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java index 6e951923117..90405968c73 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java @@ -16,6 +16,7 @@ public class TrackedEventsApi { private static final String TRACKED_EVENTS_URL = "/api/v1/events/trackedevents/"; private static final String KEY_TRACKED_EVENTS = "trackedEvents"; + private static final String KEY_REGATTA_ID = "regattaId"; private static final String KEY_EVENT_ID = "eventId"; private static final String KEY_EVENT_IS_ARCHIVED = "isArchived"; private static final String KEY_EVENT_NAME = "name"; @@ -37,6 +38,30 @@ public class TrackedEventsApi { return new TrackedEvents(ctx.get(TRACKED_EVENTS_URL, queryParams)); } + public void updateTrackedEvent(ApiContext ctx, String eventId, String regattaId, String eventBaseUrl, + String deviceId, String competitorId, String boatId, String markId) { + final JSONObject json = new JSONObject(); + json.put(KEY_EVENT_ID, eventId); + json.put(KEY_REGATTA_ID, regattaId); + json.put(KEY_EVENT_BASE_URL, eventBaseUrl); + + final JSONArray elements = new JSONArray(); + final JSONObject elem = new JSONObject(); + elem.put(KEY_TRACKED_ELEMENT_DEVICE_ID, deviceId); + if (competitorId != null) { + elem.put(KEY_TRACKED_ELEMENT_COMPETITOR_ID, competitorId); + } else if (boatId != null) { + elem.put(KEY_TRACKED_ELEMENT_BOAT_ID, boatId); + } else if (markId != null) { + elem.put(KEY_TRACKED_ELEMENT_BOAT_ID, markId); + } + elements.add(elem); + + json.put(KEY_EVENT_TRACKED_ELEMENTS, elements); + json.put(KEY_EVENT_IS_ARCHIVED, false); + ctx.put(TRACKED_EVENTS_URL, new HashMap<>(), json); + } + public class TrackedElement extends JsonWrapper { public TrackedElement(JSONObject json) { super(json); @@ -118,6 +143,10 @@ public class TrackedEventsApi { } return col; } + + public String getRegattaId() { + return get(KEY_REGATTA_ID); + } } } From 236062f43dd41a1ddd8350753a9b9c3cc95a2d24 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 25 Jun 2019 18:15:44 +0200 Subject: [PATCH 15/69] Bug 4960: changed type of regatta identifier from UUID to string --- .../server/gateway/jaxrs/api/TrackedEventsResource.java | 6 +++--- .../impl/preferences/model/TrackedEventPreference.java | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index 1a4acaca618..343231c6c84 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -105,6 +105,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { trackedElementJson.put(KEY_TRACKED_ELEMENT_MARK_ID, trackedElement.getTrackedMarkId().toString()); } + deviceIdsWithTrackedElementJson.add(trackedElementJson); } jsonEvent.put(KEY_EVENT_TRACKED_ELEMENTS, deviceIdsWithTrackedElementJson); @@ -144,7 +145,6 @@ public class TrackedEventsResource extends AbstractSailingServerResource { final String baseUrl = (String) requestObject.get(KEY_EVENT_BASE_URL); try { final UUID uuidEvent = UUID.fromString(eventId); - final UUID uuidRegatta = UUID.fromString(regattaId); final boolean isArchived = archived; TrackedEventPreferences prefs = getSecurityService().getPreferenceObject(currentUser.getName(), @@ -232,7 +232,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { while (it.hasNext()) { final TrackedEventPreference pref = it.next(); if (pref.getEventId().equals(uuidEvent) - && pref.getRegattaId().equals(uuidRegatta)) { + && pref.getRegattaId().equals(regattaId)) { prefsNew.add(new TrackedEventPreference(pref, newPrefElem)); eventContained = true; } else { @@ -242,7 +242,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { if (!eventContained) { final TrackedEventPreference newPreference = new TrackedEventPreference(uuidEvent, - uuidRegatta, Arrays.asList(newPrefElem), baseUrl, isArchived); + regattaId, Arrays.asList(newPrefElem), baseUrl, isArchived); prefsNew.add(newPreference); } diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java index 6bb9f64ef3e..1eafc50208d 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java @@ -15,7 +15,7 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings private static final long serialVersionUID = 234711768869820003L; private transient UUIDSetting eventId; - private transient UUIDSetting regattaId; + private transient StringSetting regattaId; private transient StringSetting baseUrl; private transient BooleanSetting isArchived; @@ -23,7 +23,7 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings public TrackedEventPreference() { eventId = new UUIDSetting("eventId", this); - regattaId = new UUIDSetting("regattaId", this); + regattaId = new StringSetting("regattaId", this); trackedElements = new SettingsList("trackedElements", this, () -> new TrackedElementWithDeviceId()); baseUrl = new StringSetting("baseUrl", this); @@ -63,7 +63,7 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings this.isArchived.setValue(other.getIsArchived()); } - public TrackedEventPreference(UUID eventId, UUID regattaId, Iterable trackedElements, + public TrackedEventPreference(UUID eventId, String regattaId, Iterable trackedElements, String baseUrl, boolean isArchived) { this(); this.eventId.setValue(eventId); @@ -86,7 +86,7 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings return eventId.getValue(); } - public UUID getRegattaId() { + public String getRegattaId() { return regattaId.getValue(); } From 2c46dd11f0306258449f9347a57018542da94390 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 25 Jun 2019 18:16:18 +0200 Subject: [PATCH 16/69] adjusted TrackedEventsApi (used for testing) to map JSON result correctly --- .../com/sap/sailing/selenium/api/event/TrackedEventsApi.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java index 90405968c73..775aa23fda0 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java @@ -93,7 +93,7 @@ public class TrackedEventsApi { final Collection events = new ArrayList<>(); JSONArray array = get(KEY_TRACKED_EVENTS); for (Object json : array) { - events.add((TrackedEvent) json); + events.add(new TrackedEvent((JSONObject) json)); } return events; } From 6e5fe92a78f7c5efe9c81ff0f9bdb1e0fc57048c Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 25 Jun 2019 18:28:41 +0200 Subject: [PATCH 17/69] Bug 4960: added regatta ID to json object when retrieving all tracked events --- .../sailing/server/gateway/jaxrs/api/TrackedEventsResource.java | 1 + 1 file changed, 1 insertion(+) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index 343231c6c84..8ed4084508d 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -113,6 +113,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { jsonEvent.put(KEY_EVENT_BASE_URL, pref.getBaseUrl()); jsonEvent.put(KEY_EVENT_IS_ARCHIVED, pref.getIsArchived()); jsonEvent.put(KEY_EVENT_IS_OWNER, isOwner); + jsonEvent.put(KEY_REGATTA_ID, pref.getRegattaId()); result.add(jsonEvent); } } From 56f7517aaeafe92b557b581f6cd803d054ea35bf Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 25 Jun 2019 18:29:22 +0200 Subject: [PATCH 18/69] Bug 4960: added selenium test for creating a tracked event with competitor tracking --- .../selenium/api/event/TrackedEventsApi.java | 2 +- .../test/TrackedEventsResourceApiTest.java | 52 +++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java index 775aa23fda0..901ab255bdb 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java @@ -138,7 +138,7 @@ public class TrackedEventsApi { Collection col = new ArrayList<>(); if (array != null) { for (Object w : array) { - col.add((TrackedElement) w); + col.add(new TrackedElement((JSONObject) w)); } } return col; diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java index 6b507678500..fcdd6ade8a2 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java @@ -3,12 +3,19 @@ package com.sap.sailing.selenium.api.test; import static com.sap.sailing.selenium.api.core.ApiContext.SERVER_CONTEXT; import static com.sap.sailing.selenium.api.core.ApiContext.createAdminApiContext; +import java.util.UUID; + import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import com.sap.sailing.domain.common.CompetitorRegistrationType; import com.sap.sailing.selenium.api.core.ApiContext; +import com.sap.sailing.selenium.api.event.EventApi; +import com.sap.sailing.selenium.api.event.EventApi.Event; import com.sap.sailing.selenium.api.event.TrackedEventsApi; +import com.sap.sailing.selenium.api.event.TrackedEventsApi.TrackedElement; +import com.sap.sailing.selenium.api.event.TrackedEventsApi.TrackedEvent; import com.sap.sailing.selenium.api.event.TrackedEventsApi.TrackedEvents; import com.sap.sailing.selenium.test.AbstractSeleniumTest; import com.sap.sse.common.Util; @@ -17,6 +24,8 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { private final TrackedEventsApi trackedEventsApi = new TrackedEventsApi(); + private final EventApi eventApi = new EventApi(); + @Before public void setUp() { clearState(getContextRoot()); @@ -30,4 +39,47 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { Assert.assertTrue(Util.isEmpty(trackedEvents.getEvents())); } + @Test + public void testCreateTrackedEventWithCompetitorTracking() { + final ApiContext adminCtx = createAdminApiContext(getContextRoot(), SERVER_CONTEXT); + + final String eventBaseUrl = "testUrl"; + final String deviceId = UUID.randomUUID().toString(); + final String competitorId = UUID.randomUUID().toString(); + final String boatId = null; + final String markId = null; + + Event evt = eventApi.createEvent(adminCtx, "TestEvent-" + UUID.randomUUID().toString(), "75QMNATIONALEKREUZER", + CompetitorRegistrationType.CLOSED, "Mannheim-" + UUID.randomUUID().toString()); + final String eventId = evt.getId(); + final String regattaId = evt.getName(); + + trackedEventsApi.updateTrackedEvent(adminCtx, eventId, regattaId, eventBaseUrl, deviceId, competitorId, boatId, + markId); + + // check if created event is still there + final TrackedEvents trackedEvents = trackedEventsApi.getTrackedEvents(adminCtx, true); + + boolean hasEvents = false; + for (TrackedEvent event : trackedEvents.getEvents()) { + hasEvents = true; + Assert.assertEquals(eventBaseUrl, event.getEventBaseUrl()); + Assert.assertEquals(eventId, event.getEventId()); + Assert.assertEquals(regattaId, event.getRegattaId()); + + boolean hasElements = false; + for (TrackedElement elem : event.getTrackedElements()) { + hasElements = true; + Assert.assertEquals(boatId, elem.getBoatId()); + Assert.assertEquals(competitorId, elem.getCompetitorId()); + Assert.assertEquals(deviceId, elem.getDeviceId()); + Assert.assertEquals(markId, elem.getMarkId()); + } + Assert.assertTrue(hasElements); + } + + Assert.assertTrue(hasEvents); + + } + } From b395645ab297336d9b310cc437fbd684e514281c Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 25 Jun 2019 18:50:53 +0200 Subject: [PATCH 19/69] Bug 4960: fixed conversion error in TrackedEventsResource --- .../server/gateway/jaxrs/api/TrackedEventsResource.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index 8ed4084508d..c094f87f93c 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -198,7 +198,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { markId = null; } else if (boatIdStr != null && !boatIdStr.isEmpty()) { try { - boatId = UUID.fromString(competitorIdStr); + boatId = UUID.fromString(boatIdStr); } catch (IllegalArgumentException e) { responseBuilder = Response.status(Status.BAD_REQUEST) .entity("Invalid JSON body in request."); @@ -208,7 +208,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { markId = null; } else if (markIdStr != null && !markIdStr.isEmpty()) { try { - markId = UUID.fromString(competitorIdStr); + markId = UUID.fromString(markIdStr); } catch (IllegalArgumentException e) { responseBuilder = Response.status(Status.BAD_REQUEST) .entity("Invalid JSON body in request."); From 81270c404ad756582940a780585dfe9519485ca9 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 25 Jun 2019 18:51:18 +0200 Subject: [PATCH 20/69] Bug 4960: added more test cases for TrackedEventsResource --- .../selenium/api/event/TrackedEventsApi.java | 2 +- .../test/TrackedEventsResourceApiTest.java | 24 ++++++++++++++----- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java index 901ab255bdb..40937861ae8 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java @@ -53,7 +53,7 @@ public class TrackedEventsApi { } else if (boatId != null) { elem.put(KEY_TRACKED_ELEMENT_BOAT_ID, boatId); } else if (markId != null) { - elem.put(KEY_TRACKED_ELEMENT_BOAT_ID, markId); + elem.put(KEY_TRACKED_ELEMENT_MARK_ID, markId); } elements.add(elem); diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java index fcdd6ade8a2..e0e52022e1b 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java @@ -42,15 +42,28 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { @Test public void testCreateTrackedEventWithCompetitorTracking() { final ApiContext adminCtx = createAdminApiContext(getContextRoot(), SERVER_CONTEXT); + testCreateTrackedEventWithTracking(UUID.randomUUID().toString(), null, null, adminCtx); + } - final String eventBaseUrl = "testUrl"; + @Test + public void testCreateTrackedEventWithBoatTracking() { + final ApiContext adminCtx = createAdminApiContext(getContextRoot(), SERVER_CONTEXT); + testCreateTrackedEventWithTracking(null, UUID.randomUUID().toString(), null, adminCtx); + } + + @Test + public void testCreateTrackedEventWithMarkTracking() { + final ApiContext adminCtx = createAdminApiContext(getContextRoot(), SERVER_CONTEXT); + testCreateTrackedEventWithTracking(null, null, UUID.randomUUID().toString(), adminCtx); + } + + private void testCreateTrackedEventWithTracking(final String competitorId, final String boatId, final String markId, + final ApiContext adminCtx) { + final String eventBaseUrl = "testUrl-" + UUID.randomUUID().toString(); final String deviceId = UUID.randomUUID().toString(); - final String competitorId = UUID.randomUUID().toString(); - final String boatId = null; - final String markId = null; Event evt = eventApi.createEvent(adminCtx, "TestEvent-" + UUID.randomUUID().toString(), "75QMNATIONALEKREUZER", - CompetitorRegistrationType.CLOSED, "Mannheim-" + UUID.randomUUID().toString()); + CompetitorRegistrationType.CLOSED, "Mannheim"); final String eventId = evt.getId(); final String regattaId = evt.getName(); @@ -79,7 +92,6 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { } Assert.assertTrue(hasEvents); - } } From 5ce1d4083ff83324559b8e7a897e2137f746af69 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 25 Jun 2019 19:13:07 +0200 Subject: [PATCH 21/69] Bug 4960: added test case for tracking multiple elements of the same event --- .../test/TrackedEventsResourceApiTest.java | 64 +++++++++++++++++-- 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java index e0e52022e1b..1f44aefb6d7 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java @@ -39,31 +39,81 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { Assert.assertTrue(Util.isEmpty(trackedEvents.getEvents())); } + @Test + public void testCreateMultipleTrackingsForSameEvent() { + final ApiContext adminCtx = createAdminApiContext(getContextRoot(), SERVER_CONTEXT); + final String eventName = "TestEvent-" + UUID.randomUUID().toString(); + final String competitorId = UUID.randomUUID().toString(); + final String boatId = UUID.randomUUID().toString(); + final String markId = UUID.randomUUID().toString(); + + final String eventBaseUrl = "testUrl"; + final String deviceId = UUID.randomUUID().toString(); + + final Event evt = eventApi.createEvent(adminCtx, eventName, "75QMNATIONALEKREUZER", + CompetitorRegistrationType.CLOSED, "Mannheim"); + final String eventId = evt.getId(); + final String regattaId = evt.getName(); + + trackedEventsApi.updateTrackedEvent(adminCtx, eventId, regattaId, eventBaseUrl, deviceId, competitorId, null, + null); + trackedEventsApi.updateTrackedEvent(adminCtx, eventId, regattaId, eventBaseUrl, deviceId, null, boatId, null); + trackedEventsApi.updateTrackedEvent(adminCtx, eventId, regattaId, eventBaseUrl, deviceId, null, null, markId); + + // check if created event is still there + final TrackedEvents trackedEvents = trackedEventsApi.getTrackedEvents(adminCtx, true); + + int cntEvents = 0; + for (final TrackedEvent event : trackedEvents.getEvents()) { + cntEvents++; + Assert.assertEquals(eventBaseUrl, event.getEventBaseUrl()); + Assert.assertEquals(eventId, event.getEventId()); + Assert.assertEquals(regattaId, event.getRegattaId()); + + int cntElements = 0; + for (final TrackedElement elem : event.getTrackedElements()) { + cntElements++; + final boolean correctBoatId = boatId.equals(elem.getBoatId()); + final boolean correctCompetitorId = competitorId.equals(elem.getCompetitorId()); + final boolean correctMarkId = markId.equals(elem.getMarkId()); + + Assert.assertEquals(deviceId, elem.getDeviceId()); + Assert.assertTrue(correctBoatId ^ correctCompetitorId ^ correctMarkId); + } + Assert.assertEquals(3, cntElements); + } + + Assert.assertEquals(1, cntEvents); + } + @Test public void testCreateTrackedEventWithCompetitorTracking() { final ApiContext adminCtx = createAdminApiContext(getContextRoot(), SERVER_CONTEXT); - testCreateTrackedEventWithTracking(UUID.randomUUID().toString(), null, null, adminCtx); + testCreateTrackedEventWithTracking(UUID.randomUUID().toString(), null, null, adminCtx, + "TestEvent-" + UUID.randomUUID().toString()); } @Test public void testCreateTrackedEventWithBoatTracking() { final ApiContext adminCtx = createAdminApiContext(getContextRoot(), SERVER_CONTEXT); - testCreateTrackedEventWithTracking(null, UUID.randomUUID().toString(), null, adminCtx); + testCreateTrackedEventWithTracking(null, UUID.randomUUID().toString(), null, adminCtx, + "TestEvent-" + UUID.randomUUID().toString()); } @Test public void testCreateTrackedEventWithMarkTracking() { final ApiContext adminCtx = createAdminApiContext(getContextRoot(), SERVER_CONTEXT); - testCreateTrackedEventWithTracking(null, null, UUID.randomUUID().toString(), adminCtx); + testCreateTrackedEventWithTracking(null, null, UUID.randomUUID().toString(), adminCtx, + "TestEvent-" + UUID.randomUUID().toString()); } private void testCreateTrackedEventWithTracking(final String competitorId, final String boatId, final String markId, - final ApiContext adminCtx) { - final String eventBaseUrl = "testUrl-" + UUID.randomUUID().toString(); + final ApiContext adminCtx, final String eventName) { + final String eventBaseUrl = "testUrl"; final String deviceId = UUID.randomUUID().toString(); - Event evt = eventApi.createEvent(adminCtx, "TestEvent-" + UUID.randomUUID().toString(), "75QMNATIONALEKREUZER", - CompetitorRegistrationType.CLOSED, "Mannheim"); + Event evt = eventApi.createEvent(adminCtx, eventName, "75QMNATIONALEKREUZER", CompetitorRegistrationType.CLOSED, + "Mannheim"); final String eventId = evt.getId(); final String regattaId = evt.getName(); From 35f37766652f61af742b06234b7712bd3e80f764 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 25 Jun 2019 19:16:59 +0200 Subject: [PATCH 22/69] Bug 4960: minor code cleanup --- .../sailing/selenium/api/event/TrackedEventsApi.java | 10 +++++----- .../api/test/TrackedEventsResourceApiTest.java | 7 ++++--- .../gateway/jaxrs/api/TrackedEventsResource.java | 4 ++-- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java index 40937861ae8..d17c121c8d1 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java @@ -91,8 +91,8 @@ public class TrackedEventsApi { public Iterable getEvents() { final Collection events = new ArrayList<>(); - JSONArray array = get(KEY_TRACKED_EVENTS); - for (Object json : array) { + final JSONArray array = get(KEY_TRACKED_EVENTS); + for (final Object json : array) { events.add(new TrackedEvent((JSONObject) json)); } return events; @@ -134,10 +134,10 @@ public class TrackedEventsApi { } public Iterable getTrackedElements() { - JSONArray array = get(KEY_EVENT_TRACKED_ELEMENTS); - Collection col = new ArrayList<>(); + final JSONArray array = get(KEY_EVENT_TRACKED_ELEMENTS); + final Collection col = new ArrayList<>(); if (array != null) { - for (Object w : array) { + for (final Object w : array) { col.add(new TrackedElement((JSONObject) w)); } } diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java index 1f44aefb6d7..24a69160773 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java @@ -112,7 +112,8 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { final String eventBaseUrl = "testUrl"; final String deviceId = UUID.randomUUID().toString(); - Event evt = eventApi.createEvent(adminCtx, eventName, "75QMNATIONALEKREUZER", CompetitorRegistrationType.CLOSED, + final Event evt = eventApi.createEvent(adminCtx, eventName, "75QMNATIONALEKREUZER", + CompetitorRegistrationType.CLOSED, "Mannheim"); final String eventId = evt.getId(); final String regattaId = evt.getName(); @@ -124,14 +125,14 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { final TrackedEvents trackedEvents = trackedEventsApi.getTrackedEvents(adminCtx, true); boolean hasEvents = false; - for (TrackedEvent event : trackedEvents.getEvents()) { + for (final TrackedEvent event : trackedEvents.getEvents()) { hasEvents = true; Assert.assertEquals(eventBaseUrl, event.getEventBaseUrl()); Assert.assertEquals(eventId, event.getEventId()); Assert.assertEquals(regattaId, event.getRegattaId()); boolean hasElements = false; - for (TrackedElement elem : event.getTrackedElements()) { + for (final TrackedElement elem : event.getTrackedElements()) { hasElements = true; Assert.assertEquals(boatId, elem.getBoatId()); Assert.assertEquals(competitorId, elem.getCompetitorId()); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index c094f87f93c..552ebd25b1e 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -92,7 +92,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { final JSONArray deviceIdsWithTrackedElementJson = new JSONArray(); - for (TrackedElementWithDeviceId trackedElement : pref.getTrackedElements()) { + for (final TrackedElementWithDeviceId trackedElement : pref.getTrackedElements()) { final JSONObject trackedElementJson = new JSONObject(); trackedElementJson.put(KEY_TRACKED_ELEMENT_DEVICE_ID, trackedElement.getDeviceId()); if (trackedElement.getTrackedCompetitorId() != null) { @@ -155,7 +155,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { prefs = new TrackedEventPreferences(); } - JSONArray trackedElementsJson = (JSONArray) requestObject.get(KEY_EVENT_TRACKED_ELEMENTS); + final JSONArray trackedElementsJson = (JSONArray) requestObject.get(KEY_EVENT_TRACKED_ELEMENTS); if (trackedElementsJson == null || trackedElementsJson.size() == 0) { responseBuilder = Response.status(Status.BAD_REQUEST) From 9aa6fcd06344301d41a425580bf6c99ba465c20a Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 25 Jun 2019 19:23:24 +0200 Subject: [PATCH 23/69] Bug 4960: added selenium test with multiple tracked events and event elements for TrackedEventsResource --- .../test/TrackedEventsResourceApiTest.java | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java index 24a69160773..47a3011f163 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java @@ -39,6 +39,66 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { Assert.assertTrue(Util.isEmpty(trackedEvents.getEvents())); } + @Test + public void testCreateMultipleTrackingEvents() { + final ApiContext adminCtx = createAdminApiContext(getContextRoot(), SERVER_CONTEXT); + final String competitorId = UUID.randomUUID().toString(); + final String boatId = UUID.randomUUID().toString(); + final String markId = UUID.randomUUID().toString(); + + final String eventBaseUrl = "testUrl"; + final String deviceId = UUID.randomUUID().toString(); + + final Event evt = eventApi.createEvent(adminCtx, "TestEvent-" + UUID.randomUUID().toString(), + "75QMNATIONALEKREUZER", + CompetitorRegistrationType.CLOSED, "Mannheim"); + final String eventId = evt.getId(); + final String regattaId = evt.getName(); + + final Event evt2 = eventApi.createEvent(adminCtx, "TestEvent-" + UUID.randomUUID().toString(), + "75QMNATIONALEKREUZER", + CompetitorRegistrationType.CLOSED, "Mannheim"); + final String eventId2 = evt2.getId(); + final String regattaId2 = evt2.getName(); + + trackedEventsApi.updateTrackedEvent(adminCtx, eventId, regattaId, eventBaseUrl, deviceId, competitorId, null, + null); + trackedEventsApi.updateTrackedEvent(adminCtx, eventId, regattaId, eventBaseUrl, deviceId, null, boatId, null); + trackedEventsApi.updateTrackedEvent(adminCtx, eventId2, regattaId2, eventBaseUrl, deviceId, null, null, markId); + + // check if created event is still there + final TrackedEvents trackedEvents = trackedEventsApi.getTrackedEvents(adminCtx, true); + + int cntEvents = 0; + for (final TrackedEvent event : trackedEvents.getEvents()) { + cntEvents++; + Assert.assertEquals(eventBaseUrl, event.getEventBaseUrl()); + if (eventId.equals(event.getEventId())) { + Assert.assertEquals(eventId, event.getEventId()); + Assert.assertEquals(regattaId, event.getRegattaId()); + } else if (eventId2.equals(event.getEventId())) { + Assert.assertEquals(eventId2, event.getEventId()); + Assert.assertEquals(regattaId2, event.getRegattaId()); + } else { + Assert.fail("Invalid event id."); + } + + int cntElements = 0; + for (final TrackedElement elem : event.getTrackedElements()) { + cntElements++; + final boolean correctBoatId = boatId.equals(elem.getBoatId()); + final boolean correctCompetitorId = competitorId.equals(elem.getCompetitorId()); + final boolean correctMarkId = markId.equals(elem.getMarkId()); + + Assert.assertEquals(deviceId, elem.getDeviceId()); + Assert.assertTrue(correctBoatId ^ correctCompetitorId ^ correctMarkId); + } + Assert.assertEquals(eventId.equals(event.getEventId()) ? 2 : 1, cntElements); + } + + Assert.assertEquals(2, cntEvents); + } + @Test public void testCreateMultipleTrackingsForSameEvent() { final ApiContext adminCtx = createAdminApiContext(getContextRoot(), SERVER_CONTEXT); From 664e54bd716465834501ce0c255bb281cae29ccb Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 25 Jun 2019 19:28:46 +0200 Subject: [PATCH 24/69] Bug 4960: added error messages for all asserts in TrackedventsResourceApiTest --- .../test/TrackedEventsResourceApiTest.java | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java index 47a3011f163..79bc0f0b53d 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java @@ -35,8 +35,8 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { public void testGetTrackedEventsEmpty() { final ApiContext adminCtx = createAdminApiContext(getContextRoot(), SERVER_CONTEXT); final TrackedEvents trackedEvents = trackedEventsApi.getTrackedEvents(adminCtx, true); - Assert.assertNotNull(trackedEvents); - Assert.assertTrue(Util.isEmpty(trackedEvents.getEvents())); + Assert.assertNotNull("Tracked Events element should not be null", trackedEvents); + Assert.assertTrue("Expected empty list of tracked events", Util.isEmpty(trackedEvents.getEvents())); } @Test @@ -50,14 +50,12 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { final String deviceId = UUID.randomUUID().toString(); final Event evt = eventApi.createEvent(adminCtx, "TestEvent-" + UUID.randomUUID().toString(), - "75QMNATIONALEKREUZER", - CompetitorRegistrationType.CLOSED, "Mannheim"); + "75QMNATIONALEKREUZER", CompetitorRegistrationType.CLOSED, "Mannheim"); final String eventId = evt.getId(); final String regattaId = evt.getName(); final Event evt2 = eventApi.createEvent(adminCtx, "TestEvent-" + UUID.randomUUID().toString(), - "75QMNATIONALEKREUZER", - CompetitorRegistrationType.CLOSED, "Mannheim"); + "75QMNATIONALEKREUZER", CompetitorRegistrationType.CLOSED, "Mannheim"); final String eventId2 = evt2.getId(); final String regattaId2 = evt2.getName(); @@ -72,13 +70,13 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { int cntEvents = 0; for (final TrackedEvent event : trackedEvents.getEvents()) { cntEvents++; - Assert.assertEquals(eventBaseUrl, event.getEventBaseUrl()); + Assert.assertEquals("Unexpected event base url", eventBaseUrl, event.getEventBaseUrl()); if (eventId.equals(event.getEventId())) { - Assert.assertEquals(eventId, event.getEventId()); - Assert.assertEquals(regattaId, event.getRegattaId()); + Assert.assertEquals("Unexpected event ID", eventId, event.getEventId()); + Assert.assertEquals("Unexpected regatta ID", regattaId, event.getRegattaId()); } else if (eventId2.equals(event.getEventId())) { - Assert.assertEquals(eventId2, event.getEventId()); - Assert.assertEquals(regattaId2, event.getRegattaId()); + Assert.assertEquals("Unexpected event ID", eventId2, event.getEventId()); + Assert.assertEquals("Unexpected regatta ID", regattaId2, event.getRegattaId()); } else { Assert.fail("Invalid event id."); } @@ -90,13 +88,15 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { final boolean correctCompetitorId = competitorId.equals(elem.getCompetitorId()); final boolean correctMarkId = markId.equals(elem.getMarkId()); - Assert.assertEquals(deviceId, elem.getDeviceId()); - Assert.assertTrue(correctBoatId ^ correctCompetitorId ^ correctMarkId); + Assert.assertEquals("Unexpected device ID", deviceId, elem.getDeviceId()); + Assert.assertTrue("More than one or zero items tracked in this element", + correctBoatId ^ correctCompetitorId ^ correctMarkId); } - Assert.assertEquals(eventId.equals(event.getEventId()) ? 2 : 1, cntElements); + Assert.assertEquals("Invalid numer of elements in this event", eventId.equals(event.getEventId()) ? 2 : 1, + cntElements); } - Assert.assertEquals(2, cntEvents); + Assert.assertEquals("Expected 2 events", 2, cntEvents); } @Test @@ -126,9 +126,9 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { int cntEvents = 0; for (final TrackedEvent event : trackedEvents.getEvents()) { cntEvents++; - Assert.assertEquals(eventBaseUrl, event.getEventBaseUrl()); - Assert.assertEquals(eventId, event.getEventId()); - Assert.assertEquals(regattaId, event.getRegattaId()); + Assert.assertEquals("Unexpected event base url", eventBaseUrl, event.getEventBaseUrl()); + Assert.assertEquals("Unexpected event ID", eventId, event.getEventId()); + Assert.assertEquals("Unexpected regatta ID", regattaId, event.getRegattaId()); int cntElements = 0; for (final TrackedElement elem : event.getTrackedElements()) { @@ -137,13 +137,14 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { final boolean correctCompetitorId = competitorId.equals(elem.getCompetitorId()); final boolean correctMarkId = markId.equals(elem.getMarkId()); - Assert.assertEquals(deviceId, elem.getDeviceId()); - Assert.assertTrue(correctBoatId ^ correctCompetitorId ^ correctMarkId); + Assert.assertEquals("Unexpected device ID", deviceId, elem.getDeviceId()); + Assert.assertTrue("More than one or zero items tracked in this element", + correctBoatId ^ correctCompetitorId ^ correctMarkId); } - Assert.assertEquals(3, cntElements); + Assert.assertEquals("Expected 3 event elements", 3, cntElements); } - Assert.assertEquals(1, cntEvents); + Assert.assertEquals("Expected exactly 1 event", 1, cntEvents); } @Test @@ -173,8 +174,7 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { final String deviceId = UUID.randomUUID().toString(); final Event evt = eventApi.createEvent(adminCtx, eventName, "75QMNATIONALEKREUZER", - CompetitorRegistrationType.CLOSED, - "Mannheim"); + CompetitorRegistrationType.CLOSED, "Mannheim"); final String eventId = evt.getId(); final String regattaId = evt.getName(); @@ -187,22 +187,22 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { boolean hasEvents = false; for (final TrackedEvent event : trackedEvents.getEvents()) { hasEvents = true; - Assert.assertEquals(eventBaseUrl, event.getEventBaseUrl()); - Assert.assertEquals(eventId, event.getEventId()); - Assert.assertEquals(regattaId, event.getRegattaId()); + Assert.assertEquals("Unexpected event base url", eventBaseUrl, event.getEventBaseUrl()); + Assert.assertEquals("Unexpected event ID", eventId, event.getEventId()); + Assert.assertEquals("Unexpected regatta ID", regattaId, event.getRegattaId()); boolean hasElements = false; for (final TrackedElement elem : event.getTrackedElements()) { hasElements = true; - Assert.assertEquals(boatId, elem.getBoatId()); - Assert.assertEquals(competitorId, elem.getCompetitorId()); - Assert.assertEquals(deviceId, elem.getDeviceId()); - Assert.assertEquals(markId, elem.getMarkId()); + Assert.assertEquals("Unexpected boat ID", boatId, elem.getBoatId()); + Assert.assertEquals("Unexpected competitor ID", competitorId, elem.getCompetitorId()); + Assert.assertEquals("Unexpected device ID", deviceId, elem.getDeviceId()); + Assert.assertEquals("Unexpected mark ID", markId, elem.getMarkId()); } - Assert.assertTrue(hasElements); + Assert.assertTrue("Expected at least one element", hasElements); } - Assert.assertTrue(hasEvents); + Assert.assertTrue("Expected at least one event", hasEvents); } } From 66f764a6f61a3874d56fc826361962dbea82199d Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 25 Jun 2019 19:53:16 +0200 Subject: [PATCH 25/69] Bug 4960: added feature to update the archive state for a trcked event --- .../jaxrs/api/TrackedEventsResource.java | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index 552ebd25b1e..570f8a3f722 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -3,6 +3,7 @@ package com.sap.sailing.server.gateway.jaxrs.api; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.HashSet; import java.util.Iterator; import java.util.UUID; @@ -232,8 +233,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { boolean eventContained = false; while (it.hasNext()) { final TrackedEventPreference pref = it.next(); - if (pref.getEventId().equals(uuidEvent) - && pref.getRegattaId().equals(regattaId)) { + if (pref.getEventId().equals(uuidEvent) && pref.getRegattaId().equals(regattaId)) { prefsNew.add(new TrackedEventPreference(pref, newPrefElem)); eventContained = true; } else { @@ -246,7 +246,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { regattaId, Arrays.asList(newPrefElem), baseUrl, isArchived); prefsNew.add(newPreference); } - + prefs.setTrackedEvents(prefsNew); getSecurityService().setPreferenceObject(currentUser.getName(), SailingPreferences.TRACKED_EVENTS_PREFERENCES, prefs); @@ -273,48 +273,48 @@ public class TrackedEventsResource extends AbstractSailingServerResource { @POST @Consumes(MediaType.APPLICATION_JSON) - public Response updateTrackedEvents(String jsonBody) { + public Response updateTrackedEvents(@QueryParam("eventId") String eventId, + @QueryParam("isArchived") String archived) { ResponseBuilder responseBuilder; final User currentUser = getSecurityService().getCurrentUser(); if (currentUser != null) { + final TrackedEventPreferences prefs = getSecurityService().getPreferenceObject(currentUser.getName(), + SailingPreferences.TRACKED_EVENTS_PREFERENCES); try { - final Object requestBody = JSONValue.parseWithException(jsonBody); - final JSONObject requestObject = Helpers.toJSONObjectSafe(requestBody); - final String eventId = (String) requestObject.get(KEY_EVENT_ID); - final Boolean archived = (Boolean) requestObject.get(KEY_EVENT_IS_ARCHIVED); - try { - final UUID uuid = UUID.fromString(eventId); - final boolean isArchived = archived; + final UUID eventUuid = UUID.fromString(eventId); - TrackedEventPreferences prefs = getSecurityService().getPreferenceObject(currentUser.getName(), - SailingPreferences.TRACKED_EVENTS_PREFERENCES); + final boolean isArchived = Boolean.parseBoolean(archived); + if (prefs == null) { + responseBuilder = Response.status(Status.NOT_FOUND) + .entity("No tracked events with this eventId found."); + } else { - if (prefs == null) { - prefs = new TrackedEventPreferences(); - } + boolean found = false; - final Collection prefsNew = new ArrayList<>(); - final Iterator it = prefs.getTrackedEvents().iterator(); - while (it.hasNext()) { - final TrackedEventPreference pref = it.next(); - if (pref.getEventId().equals(uuid)) { - prefsNew.add(new TrackedEventPreference(pref, isArchived)); + final Collection newPrefs = new HashSet<>(); + for (final TrackedEventPreference pref : prefs.getTrackedEvents()) { + if (pref.getEventId().equals(eventUuid)) { + found = true; + newPrefs.add(new TrackedEventPreference(pref, isArchived)); } else { - prefsNew.add(pref); + newPrefs.add(pref); } } + if (!found) { + responseBuilder = Response.status(Status.NOT_FOUND) + .entity("No tracked events with this eventId found."); + } else { + prefs.setTrackedEvents(newPrefs); + getSecurityService().setPreferenceObject(currentUser.getName(), + SailingPreferences.TRACKED_EVENTS_PREFERENCES, prefs); + responseBuilder = Response.status(Status.ACCEPTED); + } - getSecurityService().setPreferenceObject(currentUser.getName(), - SailingPreferences.TRACKED_EVENTS_PREFERENCES, prefsNew); - responseBuilder = Response.status(Status.ACCEPTED); - } catch (IllegalArgumentException | ClassCastException e) { - responseBuilder = Response.status(Status.BAD_REQUEST) - .entity("Invalid or missing attributes in JSON body."); } - } catch (ParseException | JsonDeserializationException e) { - responseBuilder = Response.status(Status.BAD_REQUEST).entity("Invalid JSON body in request."); + } catch (IllegalArgumentException e) { + responseBuilder = Response.status(Status.BAD_REQUEST).entity("Invalid eventId."); } } else { responseBuilder = Response.status(Status.UNAUTHORIZED); From b311af0ea4325c241593cda6d301ecefe4a22bc8 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 25 Jun 2019 19:53:42 +0200 Subject: [PATCH 26/69] Bug 4960: added selenium test for testing the update of the archived state in TrackedEventsResource --- .../selenium/api/event/TrackedEventsApi.java | 7 +++ .../test/TrackedEventsResourceApiTest.java | 62 +++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java index d17c121c8d1..3be35f24cf5 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java @@ -62,6 +62,13 @@ public class TrackedEventsApi { ctx.put(TRACKED_EVENTS_URL, new HashMap<>(), json); } + public void setArchived(ApiContext ctx, String eventId, boolean archived) { + final HashMap queryParams = new HashMap<>(); + queryParams.put(KEY_EVENT_ID, eventId); + queryParams.put(KEY_EVENT_IS_ARCHIVED, Boolean.toString(archived)); + ctx.post(TRACKED_EVENTS_URL, queryParams); + } + public class TrackedElement extends JsonWrapper { public TrackedElement(JSONObject json) { super(json); diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java index 79bc0f0b53d..f8335280910 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java @@ -39,6 +39,68 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { Assert.assertTrue("Expected empty list of tracked events", Util.isEmpty(trackedEvents.getEvents())); } + @Test + public void testCreateMultipleTrackingEventsAndEditOne() { + final ApiContext adminCtx = createAdminApiContext(getContextRoot(), SERVER_CONTEXT); + final String competitorId = UUID.randomUUID().toString(); + final String boatId = UUID.randomUUID().toString(); + final String markId = UUID.randomUUID().toString(); + + final String eventBaseUrl = "testUrl"; + final String deviceId = UUID.randomUUID().toString(); + + final Event evt = eventApi.createEvent(adminCtx, "TestEvent-" + UUID.randomUUID().toString(), + "75QMNATIONALEKREUZER", CompetitorRegistrationType.CLOSED, "Mannheim"); + final String eventId = evt.getId(); + final String regattaId = evt.getName(); + + final Event evt2 = eventApi.createEvent(adminCtx, "TestEvent-" + UUID.randomUUID().toString(), + "75QMNATIONALEKREUZER", CompetitorRegistrationType.CLOSED, "Mannheim"); + final String eventId2 = evt2.getId(); + final String regattaId2 = evt2.getName(); + + trackedEventsApi.updateTrackedEvent(adminCtx, eventId, regattaId, eventBaseUrl, deviceId, competitorId, null, + null); + trackedEventsApi.updateTrackedEvent(adminCtx, eventId, regattaId, eventBaseUrl, deviceId, null, boatId, null); + trackedEventsApi.updateTrackedEvent(adminCtx, eventId2, regattaId2, eventBaseUrl, deviceId, null, null, markId); + + trackedEventsApi.setArchived(adminCtx, evt.getId(), true); + trackedEventsApi.setArchived(adminCtx, evt2.getId(), false); + // check if created event is still there + final TrackedEvents trackedEvents = trackedEventsApi.getTrackedEvents(adminCtx, false); + + int cntEvents = 0; + for (final TrackedEvent event : trackedEvents.getEvents()) { + cntEvents++; + Assert.assertEquals("Unexpected event base url", eventBaseUrl, event.getEventBaseUrl()); + if (eventId.equals(event.getEventId())) { + Assert.assertEquals("Unexpected event ID", eventId, event.getEventId()); + Assert.assertEquals("Unexpected regatta ID", regattaId, event.getRegattaId()); + Assert.fail("Expected event 1 to not be shown anymore."); + } else if (eventId2.equals(event.getEventId())) { + Assert.assertEquals("Unexpected event ID", eventId2, event.getEventId()); + Assert.assertEquals("Unexpected regatta ID", regattaId2, event.getRegattaId()); + } else { + Assert.fail("Invalid event id."); + } + + int cntElements = 0; + for (final TrackedElement elem : event.getTrackedElements()) { + cntElements++; + final boolean correctBoatId = boatId.equals(elem.getBoatId()); + final boolean correctCompetitorId = competitorId.equals(elem.getCompetitorId()); + final boolean correctMarkId = markId.equals(elem.getMarkId()); + + Assert.assertEquals("Unexpected device ID", deviceId, elem.getDeviceId()); + Assert.assertTrue("More than one or zero items tracked in this element", + correctBoatId ^ correctCompetitorId ^ correctMarkId); + } + Assert.assertEquals("Invalid numer of elements in this event", 1, cntElements); + } + + Assert.assertEquals("Expected 1 events", 1, cntEvents); + } + @Test public void testCreateMultipleTrackingEvents() { final ApiContext adminCtx = createAdminApiContext(getContextRoot(), SERVER_CONTEXT); From efabf38d77e13581b7573cb7e688155761601870 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 25 Jun 2019 20:21:50 +0200 Subject: [PATCH 27/69] Bug 4960: added api endpoint to delete tracked events from TrackedEventsResource --- .../jaxrs/api/TrackedEventsResource.java | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index 570f8a3f722..59f41800eeb 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -6,12 +6,15 @@ import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.UUID; +import java.util.function.Function; import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; +import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; @@ -272,9 +275,20 @@ public class TrackedEventsResource extends AbstractSailingServerResource { } @POST - @Consumes(MediaType.APPLICATION_JSON) public Response updateTrackedEvents(@QueryParam("eventId") String eventId, @QueryParam("isArchived") String archived) { + final boolean isArchived = Boolean.parseBoolean(archived); + return applyOnEventById(eventId, pref -> new TrackedEventPreference(pref, isArchived)); + } + + @DELETE + @Path("{eventId}") + public Response deleteTrackedEvents(@PathParam("eventId") String eventId) { + return applyOnEventById(eventId, pref -> null); + } + + private Response applyOnEventById(String eventId, + Function function) { ResponseBuilder responseBuilder; final User currentUser = getSecurityService().getCurrentUser(); @@ -285,7 +299,6 @@ public class TrackedEventsResource extends AbstractSailingServerResource { try { final UUID eventUuid = UUID.fromString(eventId); - final boolean isArchived = Boolean.parseBoolean(archived); if (prefs == null) { responseBuilder = Response.status(Status.NOT_FOUND) .entity("No tracked events with this eventId found."); @@ -297,7 +310,10 @@ public class TrackedEventsResource extends AbstractSailingServerResource { for (final TrackedEventPreference pref : prefs.getTrackedEvents()) { if (pref.getEventId().equals(eventUuid)) { found = true; - newPrefs.add(new TrackedEventPreference(pref, isArchived)); + final TrackedEventPreference updatedPreference = function.apply(pref); + if (updatedPreference != null) { + newPrefs.add(updatedPreference); + } } else { newPrefs.add(pref); } From 0c511986417fe97e891ca0d3b3088581611a4b78 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 25 Jun 2019 20:22:15 +0200 Subject: [PATCH 28/69] Bug 4960: added selenium test for deleting TrackedEvents --- .../selenium/api/event/TrackedEventsApi.java | 4 ++++ .../api/test/TrackedEventsResourceApiTest.java | 18 ++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java index 3be35f24cf5..45824792d59 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java @@ -69,6 +69,10 @@ public class TrackedEventsApi { ctx.post(TRACKED_EVENTS_URL, queryParams); } + public void deleteEventTrackings(ApiContext ctx, String eventId) { + ctx.delete(TRACKED_EVENTS_URL + eventId); + } + public class TrackedElement extends JsonWrapper { public TrackedElement(JSONObject json) { super(json); diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java index f8335280910..7458db97549 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java @@ -230,8 +230,8 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { "TestEvent-" + UUID.randomUUID().toString()); } - private void testCreateTrackedEventWithTracking(final String competitorId, final String boatId, final String markId, - final ApiContext adminCtx, final String eventName) { + private String testCreateTrackedEventWithTracking(final String competitorId, final String boatId, + final String markId, final ApiContext adminCtx, final String eventName) { final String eventBaseUrl = "testUrl"; final String deviceId = UUID.randomUUID().toString(); @@ -265,6 +265,20 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { } Assert.assertTrue("Expected at least one event", hasEvents); + return eventId; + } + + @Test + public void testDeleteEvent() { + final ApiContext adminCtx = createAdminApiContext(getContextRoot(), SERVER_CONTEXT); + final String eventId = testCreateTrackedEventWithTracking(UUID.randomUUID().toString(), null, null, adminCtx, + "TestEvent-" + UUID.randomUUID().toString()); + + trackedEventsApi.deleteEventTrackings(adminCtx, eventId); + + final TrackedEvents trackedEvents = trackedEventsApi.getTrackedEvents(adminCtx, true); + Assert.assertNotNull("Tracked Events element should not be null", trackedEvents); + Assert.assertTrue("Expected empty list of tracked events", Util.isEmpty(trackedEvents.getEvents())); } } From 9183c00b276ff9245e533ccd1c2c13009bbac660 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 25 Jun 2019 20:30:07 +0200 Subject: [PATCH 29/69] Bug 4960: refactored addTackedEvent method in TrackedEventsResource --- .../jaxrs/api/TrackedEventsResource.java | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index 59f41800eeb..58173fb1650 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -161,10 +161,13 @@ public class TrackedEventsResource extends AbstractSailingServerResource { final JSONArray trackedElementsJson = (JSONArray) requestObject.get(KEY_EVENT_TRACKED_ELEMENTS); + // check that exactly one trackedElement is in JSON if (trackedElementsJson == null || trackedElementsJson.size() == 0) { + // too few children responseBuilder = Response.status(Status.BAD_REQUEST) .entity("Invalid JSON body in request: Tracked element is missing."); } else if (trackedElementsJson.size() > 1) { + // too many children responseBuilder = Response.status(Status.BAD_REQUEST).entity( "Invalid JSON body in request: Too many tracked elements: Only updating one tracked element per call is allowed."); } else { @@ -178,65 +181,48 @@ public class TrackedEventsResource extends AbstractSailingServerResource { else { + // parse IDs final String deviceId = (String) jsonTrackedElement.get(KEY_TRACKED_ELEMENT_DEVICE_ID); final String competitorIdStr = (String) jsonTrackedElement .get(KEY_TRACKED_ELEMENT_COMPETITOR_ID); final String boatIdStr = (String) jsonTrackedElement.get(KEY_TRACKED_ELEMENT_BOAT_ID); final String markIdStr = (String) jsonTrackedElement.get(KEY_TRACKED_ELEMENT_MARK_ID); - // cannot be final without either violating single point of return or multiple assignments - // in - // try/catch - UUID competitorId; - UUID boatId; - UUID markId; + // parse UUIDs of tracked element + final UUID competitorId; + final UUID boatId; + final UUID markId; if (competitorIdStr != null && !competitorIdStr.isEmpty()) { - try { - competitorId = UUID.fromString(competitorIdStr); - } catch (IllegalArgumentException e) { - responseBuilder = Response.status(Status.BAD_REQUEST) - .entity("Invalid JSON body in request."); - competitorId = null; - } + competitorId = parseUUID(competitorIdStr); boatId = null; markId = null; } else if (boatIdStr != null && !boatIdStr.isEmpty()) { - try { - boatId = UUID.fromString(boatIdStr); - } catch (IllegalArgumentException e) { - responseBuilder = Response.status(Status.BAD_REQUEST) - .entity("Invalid JSON body in request."); - boatId = null; - } competitorId = null; + boatId = parseUUID(boatIdStr); markId = null; } else if (markIdStr != null && !markIdStr.isEmpty()) { - try { - markId = UUID.fromString(markIdStr); - } catch (IllegalArgumentException e) { - responseBuilder = Response.status(Status.BAD_REQUEST) - .entity("Invalid JSON body in request."); - markId = null; - } boatId = null; competitorId = null; + markId = parseUUID(markIdStr); } else { - responseBuilder = Response.status(Status.BAD_REQUEST) - .entity("Invalid JSON body in request."); markId = boatId = competitorId = null; } if (boatId != null || markId != null || competitorId != null) { + + // create TrackedElementWithID holder final TrackedElementWithDeviceId newPrefElem = new TrackedElementWithDeviceId(deviceId, boatId, competitorId, markId); final Collection prefsNew = new ArrayList<>(); final Iterator it = prefs.getTrackedEvents().iterator(); + // add newPrefElem to correct event or create a tracked event boolean eventContained = false; while (it.hasNext()) { final TrackedEventPreference pref = it.next(); if (pref.getEventId().equals(uuidEvent) && pref.getRegattaId().equals(regattaId)) { + // tracked event found, add to event prefsNew.add(new TrackedEventPreference(pref, newPrefElem)); eventContained = true; } else { @@ -245,17 +231,21 @@ public class TrackedEventsResource extends AbstractSailingServerResource { } if (!eventContained) { + // event was not found, create a new tracked event final TrackedEventPreference newPreference = new TrackedEventPreference(uuidEvent, regattaId, Arrays.asList(newPrefElem), baseUrl, isArchived); prefsNew.add(newPreference); } + // update preferences prefs.setTrackedEvents(prefsNew); getSecurityService().setPreferenceObject(currentUser.getName(), SailingPreferences.TRACKED_EVENTS_PREFERENCES, prefs); responseBuilder = Response.status(Status.ACCEPTED); } else { // no boatId, competitorId or markId were specified + responseBuilder = Response.status(Status.BAD_REQUEST) + .entity("Invalid JSON body in request."); } } @@ -274,6 +264,16 @@ public class TrackedEventsResource extends AbstractSailingServerResource { return responseBuilder.build(); } + private UUID parseUUID(String potentialUUID) { + UUID uuid; + try { + uuid = UUID.fromString(potentialUUID); + } catch (IllegalArgumentException e) { + uuid = null; + } + return uuid; + } + @POST public Response updateTrackedEvents(@QueryParam("eventId") String eventId, @QueryParam("isArchived") String archived) { From 69c36ec6279d0f334a1a4cb4d6dbfb3f4c3d786c Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 25 Jun 2019 20:35:39 +0200 Subject: [PATCH 30/69] Bug 4960: added comments to TrackedEventsResource --- .../jaxrs/api/TrackedEventsResource.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index 58173fb1650..e404490c295 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -67,13 +67,15 @@ public class TrackedEventsResource extends AbstractSailingServerResource { // TODO: handle requests for anonymous users if (currentUser != null) { + // load tracked events from storage final TrackedEventPreferences prefs = getSecurityService().getPreferenceObject(currentUser.getName(), SailingPreferences.TRACKED_EVENTS_PREFERENCES); final JSONArray result = new JSONArray(); - final boolean showArchived = Boolean.parseBoolean(isArchived); + if (prefs != null) { + // iterate all stored tracked events for (final TrackedEventPreference pref : prefs.getTrackedEvents()) { if (!showArchived && pref.getIsArchived()) { @@ -84,6 +86,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { final UUID eventId = pref.getEventId(); final Event event = getService().getEvent(eventId); if (event != null) { + // event actually exists -> parse relevant data final OwnershipAnnotation ownership = getSecurityService().getOwnership(event.getIdentifier()); final boolean isOwner = currentUser == null ? false : currentUser.equals(ownership.getAnnotation().getUserOwner()); @@ -96,6 +99,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { final JSONArray deviceIdsWithTrackedElementJson = new JSONArray(); + // iterate all trackedElements with their associated device id and parse the data for (final TrackedElementWithDeviceId trackedElement : pref.getTrackedElements()) { final JSONObject trackedElementJson = new JSONObject(); trackedElementJson.put(KEY_TRACKED_ELEMENT_DEVICE_ID, trackedElement.getDeviceId()); @@ -123,6 +127,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { } } + // storage was empty -> respond with empty list final JSONObject resultEvents = new JSONObject(); resultEvents.put(KEY_TRACKED_EVENTS, result); final String jsonString = resultEvents.toJSONString(); @@ -287,6 +292,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { return applyOnEventById(eventId, pref -> null); } + /** Finds the tracked event with the corresponding eventId and applies the function to it. */ private Response applyOnEventById(String eventId, Function function) { ResponseBuilder responseBuilder; @@ -297,18 +303,22 @@ public class TrackedEventsResource extends AbstractSailingServerResource { final TrackedEventPreferences prefs = getSecurityService().getPreferenceObject(currentUser.getName(), SailingPreferences.TRACKED_EVENTS_PREFERENCES); try { + // parse tracked event UUID final UUID eventUuid = UUID.fromString(eventId); if (prefs == null) { + // storage is empty responseBuilder = Response.status(Status.NOT_FOUND) .entity("No tracked events with this eventId found."); } else { + // iterate stored preferences until tracked event with corresponding eventId is found boolean found = false; - final Collection newPrefs = new HashSet<>(); for (final TrackedEventPreference pref : prefs.getTrackedEvents()) { if (pref.getEventId().equals(eventUuid)) { + // tracked event found, apply function on it and remove it if result of function execution + // is null found = true; final TrackedEventPreference updatedPreference = function.apply(pref); if (updatedPreference != null) { @@ -319,9 +329,11 @@ public class TrackedEventsResource extends AbstractSailingServerResource { } } if (!found) { + // tracked event was not found -> respond with error responseBuilder = Response.status(Status.NOT_FOUND) .entity("No tracked events with this eventId found."); } else { + // update and store preferences prefs.setTrackedEvents(newPrefs); getSecurityService().setPreferenceObject(currentUser.getName(), SailingPreferences.TRACKED_EVENTS_PREFERENCES, prefs); @@ -330,6 +342,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { } } catch (IllegalArgumentException e) { + // eventId parameter could not be parsed responseBuilder = Response.status(Status.BAD_REQUEST).entity("Invalid eventId."); } } else { From 92deb8634a09ff104471b8d2453278cc9ce21421 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Wed, 26 Jun 2019 13:34:01 +0200 Subject: [PATCH 31/69] Bug 4960: added read permission check and returned alternative element --- .../jaxrs/api/TrackedEventsResource.java | 83 +++++++++++-------- 1 file changed, 48 insertions(+), 35 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index e404490c295..0cc58c9017f 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -64,7 +64,6 @@ public class TrackedEventsResource extends AbstractSailingServerResource { final ResponseBuilder builder; // check if user logged in - // TODO: handle requests for anonymous users if (currentUser != null) { // load tracked events from storage @@ -86,43 +85,39 @@ public class TrackedEventsResource extends AbstractSailingServerResource { final UUID eventId = pref.getEventId(); final Event event = getService().getEvent(eventId); if (event != null) { - // event actually exists -> parse relevant data - final OwnershipAnnotation ownership = getSecurityService().getOwnership(event.getIdentifier()); - final boolean isOwner = currentUser == null ? false - : currentUser.equals(ownership.getAnnotation().getUserOwner()); + if (getSecurityService().hasCurrentUserReadPermission(event)) { + // event actually exists -> parse relevant data + final OwnershipAnnotation ownership = getSecurityService() + .getOwnership(event.getIdentifier()); + final boolean isOwner = currentUser == null ? false + : currentUser.equals(ownership.getAnnotation().getUserOwner()); - final JSONObject jsonEvent = new JSONObject(); - jsonEvent.put(KEY_EVENT_ID, event.getId().toString()); - jsonEvent.put(KEY_EVENT_NAME, event.getName()); - jsonEvent.put(KEY_EVENT_START, event.getStartDate().toString()); - jsonEvent.put(KEY_EVENT_AND, event.getEndDate().toString()); + final JSONObject jsonEvent = new JSONObject(); + jsonEvent.put(KEY_EVENT_ID, event.getId().toString()); + jsonEvent.put(KEY_EVENT_NAME, event.getName()); + jsonEvent.put(KEY_EVENT_START, event.getStartDate().toString()); + jsonEvent.put(KEY_EVENT_AND, event.getEndDate().toString()); - final JSONArray deviceIdsWithTrackedElementJson = new JSONArray(); - - // iterate all trackedElements with their associated device id and parse the data - for (final TrackedElementWithDeviceId trackedElement : pref.getTrackedElements()) { - final JSONObject trackedElementJson = new JSONObject(); - trackedElementJson.put(KEY_TRACKED_ELEMENT_DEVICE_ID, trackedElement.getDeviceId()); - if (trackedElement.getTrackedCompetitorId() != null) { - trackedElementJson.put(KEY_TRACKED_ELEMENT_COMPETITOR_ID, - trackedElement.getTrackedCompetitorId().toString()); - } else if (trackedElement.getTrackedBoatId() != null) { - trackedElementJson.put(KEY_TRACKED_ELEMENT_BOAT_ID, - trackedElement.getTrackedBoatId().toString()); - } else if (trackedElement.getTrackedMarkId() != null) { - trackedElementJson.put(KEY_TRACKED_ELEMENT_MARK_ID, - trackedElement.getTrackedMarkId().toString()); - } - deviceIdsWithTrackedElementJson.add(trackedElementJson); + jsonEvent.put(KEY_EVENT_TRACKED_ELEMENTS, trackedElementsToJson(pref)); + // jsonEvent.put("imageUrl", event.getImages().) + jsonEvent.put(KEY_EVENT_BASE_URL, pref.getBaseUrl()); + jsonEvent.put(KEY_EVENT_IS_ARCHIVED, pref.getIsArchived()); + jsonEvent.put(KEY_EVENT_IS_OWNER, isOwner); + jsonEvent.put(KEY_REGATTA_ID, pref.getRegattaId()); + result.add(jsonEvent); + } else { + // User does not have read permission on event + final JSONObject jsonEvent = new JSONObject(); + jsonEvent.put(KEY_EVENT_ID, pref.getEventId()); + jsonEvent.put(KEY_REGATTA_ID, pref.getRegattaId()); + jsonEvent.put(KEY_EVENT_BASE_URL, pref.getBaseUrl()); + jsonEvent.put(KEY_EVENT_IS_ARCHIVED, pref.getIsArchived()); + jsonEvent.put(KEY_EVENT_TRACKED_ELEMENTS, trackedElementsToJson(pref)); + result.add(jsonEvent); } - - jsonEvent.put(KEY_EVENT_TRACKED_ELEMENTS, deviceIdsWithTrackedElementJson); - // jsonEvent.put("imageUrl", event.getImages().) - jsonEvent.put(KEY_EVENT_BASE_URL, pref.getBaseUrl()); - jsonEvent.put(KEY_EVENT_IS_ARCHIVED, pref.getIsArchived()); - jsonEvent.put(KEY_EVENT_IS_OWNER, isOwner); - jsonEvent.put(KEY_REGATTA_ID, pref.getRegattaId()); - result.add(jsonEvent); + } else { + // TODO: + // check, if base url is equal to this server, if not, event might be on different server } } } @@ -138,6 +133,24 @@ public class TrackedEventsResource extends AbstractSailingServerResource { return builder.build(); } + private JSONArray trackedElementsToJson(final TrackedEventPreference pref) { + final JSONArray deviceIdsWithTrackedElementJson = new JSONArray(); + for (final TrackedElementWithDeviceId trackedElement : pref.getTrackedElements()) { + final JSONObject trackedElementJson = new JSONObject(); + trackedElementJson.put(KEY_TRACKED_ELEMENT_DEVICE_ID, trackedElement.getDeviceId()); + if (trackedElement.getTrackedCompetitorId() != null) { + trackedElementJson.put(KEY_TRACKED_ELEMENT_COMPETITOR_ID, + trackedElement.getTrackedCompetitorId().toString()); + } else if (trackedElement.getTrackedBoatId() != null) { + trackedElementJson.put(KEY_TRACKED_ELEMENT_BOAT_ID, trackedElement.getTrackedBoatId().toString()); + } else if (trackedElement.getTrackedMarkId() != null) { + trackedElementJson.put(KEY_TRACKED_ELEMENT_MARK_ID, trackedElement.getTrackedMarkId().toString()); + } + deviceIdsWithTrackedElementJson.add(trackedElementJson); + } + return deviceIdsWithTrackedElementJson; + } + @PUT @Consumes(MediaType.APPLICATION_JSON) public Response addTrackedEvent(String jsonBody) { From 9ddbec1eb3f2b2042cfe480e9664cc12fdb1fb8e Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Wed, 26 Jun 2019 13:40:08 +0200 Subject: [PATCH 32/69] Bug 4960: added retrival of logo image to --- .../gateway/jaxrs/api/TrackedEventsResource.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index 0cc58c9017f..32aebf1223d 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -5,6 +5,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.UUID; import java.util.function.Function; @@ -35,8 +36,10 @@ import com.sap.sailing.server.impl.preferences.model.SailingPreferences; import com.sap.sailing.server.impl.preferences.model.TrackedElementWithDeviceId; import com.sap.sailing.server.impl.preferences.model.TrackedEventPreference; import com.sap.sailing.server.impl.preferences.model.TrackedEventPreferences; +import com.sap.sse.common.media.MediaTagConstants; import com.sap.sse.security.shared.OwnershipAnnotation; import com.sap.sse.security.shared.impl.User; +import com.sap.sse.shared.media.ImageDescriptor; @Path("/v1/events/trackedevents/") public class TrackedEventsResource extends AbstractSailingServerResource { @@ -50,6 +53,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { private static final String KEY_EVENT_TRACKED_ELEMENTS = "trackedElements"; private static final String KEY_EVENT_BASE_URL = "url"; private static final String KEY_EVENT_IS_OWNER = "isOwner"; + private static final String KEY_EVENT_IMAGE_URL = "imageUrl"; private static final String KEY_TRACKED_ELEMENT_DEVICE_ID = "deviceId"; private static final String KEY_TRACKED_ELEMENT_COMPETITOR_ID = "competitorId"; private static final String KEY_TRACKED_ELEMENT_BOAT_ID = "boatId"; @@ -99,7 +103,11 @@ public class TrackedEventsResource extends AbstractSailingServerResource { jsonEvent.put(KEY_EVENT_AND, event.getEndDate().toString()); jsonEvent.put(KEY_EVENT_TRACKED_ELEMENTS, trackedElementsToJson(pref)); - // jsonEvent.put("imageUrl", event.getImages().) + final List imageWithLogoTag = event + .findImagesWithTag(MediaTagConstants.LOGO.getName()); + if (!imageWithLogoTag.isEmpty()) { + jsonEvent.put(KEY_EVENT_IMAGE_URL, imageWithLogoTag.get(0).getURL().toExternalForm()); + } jsonEvent.put(KEY_EVENT_BASE_URL, pref.getBaseUrl()); jsonEvent.put(KEY_EVENT_IS_ARCHIVED, pref.getIsArchived()); jsonEvent.put(KEY_EVENT_IS_OWNER, isOwner); @@ -110,6 +118,11 @@ public class TrackedEventsResource extends AbstractSailingServerResource { final JSONObject jsonEvent = new JSONObject(); jsonEvent.put(KEY_EVENT_ID, pref.getEventId()); jsonEvent.put(KEY_REGATTA_ID, pref.getRegattaId()); + final List imageWithLogoTag = event + .findImagesWithTag(MediaTagConstants.LOGO.getName()); + if (!imageWithLogoTag.isEmpty()) { + jsonEvent.put(KEY_EVENT_IMAGE_URL, imageWithLogoTag.get(0).getURL().toExternalForm()); + } jsonEvent.put(KEY_EVENT_BASE_URL, pref.getBaseUrl()); jsonEvent.put(KEY_EVENT_IS_ARCHIVED, pref.getIsArchived()); jsonEvent.put(KEY_EVENT_TRACKED_ELEMENTS, trackedElementsToJson(pref)); From c1184ca88c50befc4c59779b169dbfafb8c5deb7 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Wed, 26 Jun 2019 13:41:09 +0200 Subject: [PATCH 33/69] Bug 4960: renamed TrackedEventsResource.add method to updateOrCreateTrackedEvent --- .../sailing/server/gateway/jaxrs/api/TrackedEventsResource.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index 32aebf1223d..4c6369bf49d 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -166,7 +166,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { @PUT @Consumes(MediaType.APPLICATION_JSON) - public Response addTrackedEvent(String jsonBody) { + public Response updateOrCreateTrackedEvent(String jsonBody) { ResponseBuilder responseBuilder = null; final User currentUser = getSecurityService().getCurrentUser(); From e234ca5be5e9adb9a8b2baca4594207788ff9430 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Wed, 26 Jun 2019 13:45:49 +0200 Subject: [PATCH 34/69] Bug 4960: adjusted TRackedEventPreference(s) to use correct addChildSettings()-method --- .../model/TrackedEventPreference.java | 17 ++++++----------- .../model/TrackedEventPreferences.java | 7 +------ 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java index 1eafc50208d..5c9750ef087 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java @@ -22,12 +22,6 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings private transient SettingsList trackedElements; public TrackedEventPreference() { - eventId = new UUIDSetting("eventId", this); - regattaId = new StringSetting("regattaId", this); - trackedElements = new SettingsList("trackedElements", this, - () -> new TrackedElementWithDeviceId()); - baseUrl = new StringSetting("baseUrl", this); - isArchived = new BooleanSetting("isArchived", this); } /** copy constructor */ @@ -75,11 +69,12 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings @Override protected void addChildSettings() { - // We do not create the Setting instances here, because access to the RacingEventService would not be given. - // Doing this, Java/GWT Serialization isn't working anymore. Because the preferences are only serialized as JSON - // in the backend an transferred as DTO to the frontend, this isn't a problem. Due to usage of BoatClass and - // Competitor domain objects, it wouldn't be GWT compatible anyway. - // The usage of Java Serialization isn't planned by now, either. + eventId = new UUIDSetting("eventId", this); + regattaId = new StringSetting("regattaId", this); + trackedElements = new SettingsList("trackedElements", this, + () -> new TrackedElementWithDeviceId()); + baseUrl = new StringSetting("baseUrl", this); + isArchived = new BooleanSetting("isArchived", this); } public UUID getEventId() { diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreferences.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreferences.java index 076949ca7c7..5afc09d55d4 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreferences.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreferences.java @@ -13,16 +13,11 @@ public class TrackedEventPreferences extends AbstractGenericSerializableSettings private transient SettingsList trackedEvents; public TrackedEventPreferences() { - trackedEvents = new SettingsList<>("trackedEvents", this, () -> new TrackedEventPreference()); } @Override protected void addChildSettings() { - // We do not create the Setting instances here, because access to the RacingEventService would not be given. - // Doing this, Java/GWT Serialization isn't working anymore. Because the preferences are only serialized as JSON - // in the backend an transferred as DTO to the frontend, this isn't a problem. Due to usage of BoatClass and - // Competitor domain objects, it wouldn't be GWT compatible anyway. - // The usage of Java Serialization isn't planned by now, either. + trackedEvents = new SettingsList<>("trackedEvents", this, () -> new TrackedEventPreference()); } public Iterable getTrackedEvents() { From e36006acdd04f46f548bbe0cb71a10e887c8caf4 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Wed, 26 Jun 2019 13:50:42 +0200 Subject: [PATCH 35/69] Bug 4960: replaced lambdas by constructor references --- .../src/com/sap/sailing/server/impl/Activator.java | 4 ++-- .../impl/preferences/model/TrackedEventPreferences.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/Activator.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/Activator.java index 49c82a475bb..6a049d99f6c 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/Activator.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/Activator.java @@ -154,7 +154,7 @@ public class Activator implements BundleActivator { properties)); properties.put(PreferenceConverter.KEY_PARAMETER_NAME, StoredDataMiningQueryPreferences.PREF_NAME); registrations.add(context.registerService(PreferenceConverter.class, - new GenericJSONPreferenceConverter<>(() -> new StoredDataMiningQueryPreferences()), properties)); + new GenericJSONPreferenceConverter<>(StoredDataMiningQueryPreferences::new), properties)); properties.put(PreferenceConverter.KEY_PARAMETER_NAME, SailorProfilePreferences.PREF_NAME); registrations.add(context.registerService(PreferenceConverter.class, new GenericJSONPreferenceConverter<>( @@ -162,7 +162,7 @@ public class Activator implements BundleActivator { properties)); properties.put(PreferenceConverter.KEY_PARAMETER_NAME, TrackedEventPreferences.PREF_NAME); registrations.add(context.registerService(PreferenceConverter.class, - new GenericJSONPreferenceConverter<>(() -> new TrackedEventPreferences()), properties)); + new GenericJSONPreferenceConverter<>(TrackedEventPreferences::new), properties)); } public static BundleContext getContext() { diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreferences.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreferences.java index 5afc09d55d4..d4745dee645 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreferences.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreferences.java @@ -17,7 +17,7 @@ public class TrackedEventPreferences extends AbstractGenericSerializableSettings @Override protected void addChildSettings() { - trackedEvents = new SettingsList<>("trackedEvents", this, () -> new TrackedEventPreference()); + trackedEvents = new SettingsList<>("trackedEvents", this, TrackedEventPreference::new); } public Iterable getTrackedEvents() { From 6e028468ad17588f67a82ea98b60811f530858f0 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Wed, 26 Jun 2019 13:51:29 +0200 Subject: [PATCH 36/69] Bug 4960: removed now unnecessary TrackedElementType --- .../server/impl/preferences/model/TrackedElementType.java | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedElementType.java diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedElementType.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedElementType.java deleted file mode 100644 index 06c2aabab53..00000000000 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedElementType.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.sap.sailing.server.impl.preferences.model; - -public enum TrackedElementType { - Boat, Competitor, Mark; -} From a4f7bcdd0407a7775a04cb552a2bd829ebc6d063 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Wed, 26 Jun 2019 14:11:25 +0200 Subject: [PATCH 37/69] Bug 4960: changed query parameter 'isArchived' to 'includeArchived' to avoid confusion with the attribute 'isArchived' of a tracked event --- .../selenium/api/event/TrackedEventsApi.java | 6 ++++-- .../gateway/jaxrs/api/TrackedEventsResource.java | 14 ++++++++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java index 45824792d59..8a3394ec4e5 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java @@ -32,9 +32,11 @@ public class TrackedEventsApi { private static final String KEY_TRACKED_ELEMENT_BOAT_ID = "boatId"; private static final String KEY_TRACKED_ELEMENT_MARK_ID = "markId"; + private static final String KEY_QUERY_INCLUDE_ARCHIVED = "includeArchived"; + public TrackedEvents getTrackedEvents(ApiContext ctx, boolean isArchived) { final Map queryParams = new HashMap<>(); - queryParams.put(KEY_EVENT_IS_ARCHIVED, Boolean.toString(isArchived)); + queryParams.put(KEY_QUERY_INCLUDE_ARCHIVED, Boolean.toString(isArchived)); return new TrackedEvents(ctx.get(TRACKED_EVENTS_URL, queryParams)); } @@ -65,7 +67,7 @@ public class TrackedEventsApi { public void setArchived(ApiContext ctx, String eventId, boolean archived) { final HashMap queryParams = new HashMap<>(); queryParams.put(KEY_EVENT_ID, eventId); - queryParams.put(KEY_EVENT_IS_ARCHIVED, Boolean.toString(archived)); + queryParams.put(KEY_QUERY_INCLUDE_ARCHIVED, Boolean.toString(archived)); ctx.post(TRACKED_EVENTS_URL, queryParams); } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index 4c6369bf49d..d1a83b17d6c 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -44,6 +44,8 @@ import com.sap.sse.shared.media.ImageDescriptor; @Path("/v1/events/trackedevents/") public class TrackedEventsResource extends AbstractSailingServerResource { + private static final String KEY_QUERY_INCLUDE_ARCHIVED = "includeArchived"; + private static final String KEY_REGATTA_ID = "regattaId"; private static final String KEY_EVENT_ID = "eventId"; private static final String KEY_EVENT_IS_ARCHIVED = "isArchived"; @@ -62,7 +64,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { @GET @Produces("application/json;charset=UTF-8") - public Response getTrackedEvents(@QueryParam(KEY_EVENT_IS_ARCHIVED) String isArchived) { + public Response getTrackedEvents(@QueryParam(KEY_QUERY_INCLUDE_ARCHIVED) String includeArchivedStr) { final User currentUser = getSecurityService().getCurrentUser(); final ResponseBuilder builder; @@ -75,13 +77,13 @@ public class TrackedEventsResource extends AbstractSailingServerResource { SailingPreferences.TRACKED_EVENTS_PREFERENCES); final JSONArray result = new JSONArray(); - final boolean showArchived = Boolean.parseBoolean(isArchived); + final boolean includeArchived = Boolean.parseBoolean(includeArchivedStr); if (prefs != null) { // iterate all stored tracked events for (final TrackedEventPreference pref : prefs.getTrackedEvents()) { - if (!showArchived && pref.getIsArchived()) { + if (!includeArchived && pref.getIsArchived()) { // skip, if event is archived and should be filtered out continue; } @@ -306,15 +308,15 @@ public class TrackedEventsResource extends AbstractSailingServerResource { } @POST - public Response updateTrackedEvents(@QueryParam("eventId") String eventId, - @QueryParam("isArchived") String archived) { + public Response updateTrackedEventsArchivedStatus(@QueryParam(KEY_EVENT_ID) String eventId, + @QueryParam(KEY_QUERY_INCLUDE_ARCHIVED) String archived) { final boolean isArchived = Boolean.parseBoolean(archived); return applyOnEventById(eventId, pref -> new TrackedEventPreference(pref, isArchived)); } @DELETE @Path("{eventId}") - public Response deleteTrackedEvents(@PathParam("eventId") String eventId) { + public Response deleteTrackedEvents(@PathParam(KEY_EVENT_ID) String eventId) { return applyOnEventById(eventId, pref -> null); } From 318970d92d980152b129171709d48389b4f4254e Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Wed, 26 Jun 2019 14:19:46 +0200 Subject: [PATCH 38/69] Bug 4960: renamed regattaId to leaderboardName, since it actually contains the leaderboard name which is the regatta id --- .../selenium/api/event/TrackedEventsApi.java | 10 ++-- .../test/TrackedEventsResourceApiTest.java | 52 +++++++++++-------- .../jaxrs/api/TrackedEventsResource.java | 13 ++--- .../model/TrackedEventPreference.java | 20 +++---- 4 files changed, 51 insertions(+), 44 deletions(-) diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java index 8a3394ec4e5..615fdb9fb35 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java @@ -16,7 +16,7 @@ public class TrackedEventsApi { private static final String TRACKED_EVENTS_URL = "/api/v1/events/trackedevents/"; private static final String KEY_TRACKED_EVENTS = "trackedEvents"; - private static final String KEY_REGATTA_ID = "regattaId"; + private static final String KEY_LEADERBOARD_NAME = "leaderboardName"; private static final String KEY_EVENT_ID = "eventId"; private static final String KEY_EVENT_IS_ARCHIVED = "isArchived"; private static final String KEY_EVENT_NAME = "name"; @@ -40,11 +40,11 @@ public class TrackedEventsApi { return new TrackedEvents(ctx.get(TRACKED_EVENTS_URL, queryParams)); } - public void updateTrackedEvent(ApiContext ctx, String eventId, String regattaId, String eventBaseUrl, + public void updateTrackedEvent(ApiContext ctx, String eventId, String leaderboardName, String eventBaseUrl, String deviceId, String competitorId, String boatId, String markId) { final JSONObject json = new JSONObject(); json.put(KEY_EVENT_ID, eventId); - json.put(KEY_REGATTA_ID, regattaId); + json.put(KEY_LEADERBOARD_NAME, leaderboardName); json.put(KEY_EVENT_BASE_URL, eventBaseUrl); final JSONArray elements = new JSONArray(); @@ -157,8 +157,8 @@ public class TrackedEventsApi { return col; } - public String getRegattaId() { - return get(KEY_REGATTA_ID); + public String getLeaderboardName() { + return get(KEY_LEADERBOARD_NAME); } } diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java index 7458db97549..4a2d32dfa2c 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java @@ -52,17 +52,19 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { final Event evt = eventApi.createEvent(adminCtx, "TestEvent-" + UUID.randomUUID().toString(), "75QMNATIONALEKREUZER", CompetitorRegistrationType.CLOSED, "Mannheim"); final String eventId = evt.getId(); - final String regattaId = evt.getName(); + final String leaderboardName = evt.getName(); final Event evt2 = eventApi.createEvent(adminCtx, "TestEvent-" + UUID.randomUUID().toString(), "75QMNATIONALEKREUZER", CompetitorRegistrationType.CLOSED, "Mannheim"); final String eventId2 = evt2.getId(); - final String regattaId2 = evt2.getName(); + final String leaderboardName2 = evt2.getName(); - trackedEventsApi.updateTrackedEvent(adminCtx, eventId, regattaId, eventBaseUrl, deviceId, competitorId, null, + trackedEventsApi.updateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, competitorId, + null, null); + trackedEventsApi.updateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, null, boatId, null); - trackedEventsApi.updateTrackedEvent(adminCtx, eventId, regattaId, eventBaseUrl, deviceId, null, boatId, null); - trackedEventsApi.updateTrackedEvent(adminCtx, eventId2, regattaId2, eventBaseUrl, deviceId, null, null, markId); + trackedEventsApi.updateTrackedEvent(adminCtx, eventId2, leaderboardName2, eventBaseUrl, deviceId, null, null, + markId); trackedEventsApi.setArchived(adminCtx, evt.getId(), true); trackedEventsApi.setArchived(adminCtx, evt2.getId(), false); @@ -75,11 +77,11 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { Assert.assertEquals("Unexpected event base url", eventBaseUrl, event.getEventBaseUrl()); if (eventId.equals(event.getEventId())) { Assert.assertEquals("Unexpected event ID", eventId, event.getEventId()); - Assert.assertEquals("Unexpected regatta ID", regattaId, event.getRegattaId()); + Assert.assertEquals("Unexpected leaderboard name", leaderboardName, event.getLeaderboardName()); Assert.fail("Expected event 1 to not be shown anymore."); } else if (eventId2.equals(event.getEventId())) { Assert.assertEquals("Unexpected event ID", eventId2, event.getEventId()); - Assert.assertEquals("Unexpected regatta ID", regattaId2, event.getRegattaId()); + Assert.assertEquals("Unexpected leaderboard name", leaderboardName2, event.getLeaderboardName()); } else { Assert.fail("Invalid event id."); } @@ -114,17 +116,19 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { final Event evt = eventApi.createEvent(adminCtx, "TestEvent-" + UUID.randomUUID().toString(), "75QMNATIONALEKREUZER", CompetitorRegistrationType.CLOSED, "Mannheim"); final String eventId = evt.getId(); - final String regattaId = evt.getName(); + final String leaderboardName = evt.getName(); final Event evt2 = eventApi.createEvent(adminCtx, "TestEvent-" + UUID.randomUUID().toString(), "75QMNATIONALEKREUZER", CompetitorRegistrationType.CLOSED, "Mannheim"); final String eventId2 = evt2.getId(); - final String regattaId2 = evt2.getName(); + final String leaderboardName2 = evt2.getName(); - trackedEventsApi.updateTrackedEvent(adminCtx, eventId, regattaId, eventBaseUrl, deviceId, competitorId, null, + trackedEventsApi.updateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, competitorId, + null, null); + trackedEventsApi.updateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, null, boatId, null); - trackedEventsApi.updateTrackedEvent(adminCtx, eventId, regattaId, eventBaseUrl, deviceId, null, boatId, null); - trackedEventsApi.updateTrackedEvent(adminCtx, eventId2, regattaId2, eventBaseUrl, deviceId, null, null, markId); + trackedEventsApi.updateTrackedEvent(adminCtx, eventId2, leaderboardName2, eventBaseUrl, deviceId, null, null, + markId); // check if created event is still there final TrackedEvents trackedEvents = trackedEventsApi.getTrackedEvents(adminCtx, true); @@ -135,10 +139,10 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { Assert.assertEquals("Unexpected event base url", eventBaseUrl, event.getEventBaseUrl()); if (eventId.equals(event.getEventId())) { Assert.assertEquals("Unexpected event ID", eventId, event.getEventId()); - Assert.assertEquals("Unexpected regatta ID", regattaId, event.getRegattaId()); + Assert.assertEquals("Unexpected leaderboard name", leaderboardName, event.getLeaderboardName()); } else if (eventId2.equals(event.getEventId())) { Assert.assertEquals("Unexpected event ID", eventId2, event.getEventId()); - Assert.assertEquals("Unexpected regatta ID", regattaId2, event.getRegattaId()); + Assert.assertEquals("Unexpected leaderboard name", leaderboardName2, event.getLeaderboardName()); } else { Assert.fail("Invalid event id."); } @@ -175,12 +179,14 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { final Event evt = eventApi.createEvent(adminCtx, eventName, "75QMNATIONALEKREUZER", CompetitorRegistrationType.CLOSED, "Mannheim"); final String eventId = evt.getId(); - final String regattaId = evt.getName(); + final String leaderboardName = evt.getName(); - trackedEventsApi.updateTrackedEvent(adminCtx, eventId, regattaId, eventBaseUrl, deviceId, competitorId, null, + trackedEventsApi.updateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, competitorId, + null, null); + trackedEventsApi.updateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, null, boatId, null); - trackedEventsApi.updateTrackedEvent(adminCtx, eventId, regattaId, eventBaseUrl, deviceId, null, boatId, null); - trackedEventsApi.updateTrackedEvent(adminCtx, eventId, regattaId, eventBaseUrl, deviceId, null, null, markId); + trackedEventsApi.updateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, null, null, + markId); // check if created event is still there final TrackedEvents trackedEvents = trackedEventsApi.getTrackedEvents(adminCtx, true); @@ -190,7 +196,7 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { cntEvents++; Assert.assertEquals("Unexpected event base url", eventBaseUrl, event.getEventBaseUrl()); Assert.assertEquals("Unexpected event ID", eventId, event.getEventId()); - Assert.assertEquals("Unexpected regatta ID", regattaId, event.getRegattaId()); + Assert.assertEquals("Unexpected leaderboard name", leaderboardName, event.getLeaderboardName()); int cntElements = 0; for (final TrackedElement elem : event.getTrackedElements()) { @@ -238,10 +244,10 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { final Event evt = eventApi.createEvent(adminCtx, eventName, "75QMNATIONALEKREUZER", CompetitorRegistrationType.CLOSED, "Mannheim"); final String eventId = evt.getId(); - final String regattaId = evt.getName(); + final String leaderboardName = evt.getName(); - trackedEventsApi.updateTrackedEvent(adminCtx, eventId, regattaId, eventBaseUrl, deviceId, competitorId, boatId, - markId); + trackedEventsApi.updateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, competitorId, + boatId, markId); // check if created event is still there final TrackedEvents trackedEvents = trackedEventsApi.getTrackedEvents(adminCtx, true); @@ -251,7 +257,7 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { hasEvents = true; Assert.assertEquals("Unexpected event base url", eventBaseUrl, event.getEventBaseUrl()); Assert.assertEquals("Unexpected event ID", eventId, event.getEventId()); - Assert.assertEquals("Unexpected regatta ID", regattaId, event.getRegattaId()); + Assert.assertEquals("Unexpected leaderboard name", leaderboardName, event.getLeaderboardName()); boolean hasElements = false; for (final TrackedElement elem : event.getTrackedElements()) { diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index d1a83b17d6c..aa270a83cd6 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -46,7 +46,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { private static final String KEY_QUERY_INCLUDE_ARCHIVED = "includeArchived"; - private static final String KEY_REGATTA_ID = "regattaId"; + private static final String KEY_LEADERBOARD_NAME = "leaderboardName"; private static final String KEY_EVENT_ID = "eventId"; private static final String KEY_EVENT_IS_ARCHIVED = "isArchived"; private static final String KEY_EVENT_NAME = "name"; @@ -113,13 +113,13 @@ public class TrackedEventsResource extends AbstractSailingServerResource { jsonEvent.put(KEY_EVENT_BASE_URL, pref.getBaseUrl()); jsonEvent.put(KEY_EVENT_IS_ARCHIVED, pref.getIsArchived()); jsonEvent.put(KEY_EVENT_IS_OWNER, isOwner); - jsonEvent.put(KEY_REGATTA_ID, pref.getRegattaId()); + jsonEvent.put(KEY_LEADERBOARD_NAME, pref.getLeaderboardName()); result.add(jsonEvent); } else { // User does not have read permission on event final JSONObject jsonEvent = new JSONObject(); jsonEvent.put(KEY_EVENT_ID, pref.getEventId()); - jsonEvent.put(KEY_REGATTA_ID, pref.getRegattaId()); + jsonEvent.put(KEY_LEADERBOARD_NAME, pref.getLeaderboardName()); final List imageWithLogoTag = event .findImagesWithTag(MediaTagConstants.LOGO.getName()); if (!imageWithLogoTag.isEmpty()) { @@ -178,7 +178,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { final Object requestBody = JSONValue.parseWithException(jsonBody); final JSONObject requestObject = Helpers.toJSONObjectSafe(requestBody); final String eventId = (String) requestObject.get(KEY_EVENT_ID); - final String regattaId = (String) requestObject.get(KEY_REGATTA_ID); + final String leaderboardName = (String) requestObject.get(KEY_LEADERBOARD_NAME); final Boolean archived = (Boolean) requestObject.get(KEY_EVENT_IS_ARCHIVED); final String baseUrl = (String) requestObject.get(KEY_EVENT_BASE_URL); try { @@ -254,7 +254,8 @@ public class TrackedEventsResource extends AbstractSailingServerResource { boolean eventContained = false; while (it.hasNext()) { final TrackedEventPreference pref = it.next(); - if (pref.getEventId().equals(uuidEvent) && pref.getRegattaId().equals(regattaId)) { + if (pref.getEventId().equals(uuidEvent) + && pref.getLeaderboardName().equals(leaderboardName)) { // tracked event found, add to event prefsNew.add(new TrackedEventPreference(pref, newPrefElem)); eventContained = true; @@ -266,7 +267,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { if (!eventContained) { // event was not found, create a new tracked event final TrackedEventPreference newPreference = new TrackedEventPreference(uuidEvent, - regattaId, Arrays.asList(newPrefElem), baseUrl, isArchived); + leaderboardName, Arrays.asList(newPrefElem), baseUrl, isArchived); prefsNew.add(newPreference); } diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java index 5c9750ef087..96b828caaba 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java @@ -15,7 +15,7 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings private static final long serialVersionUID = 234711768869820003L; private transient UUIDSetting eventId; - private transient StringSetting regattaId; + private transient StringSetting leaderboardName; private transient StringSetting baseUrl; private transient BooleanSetting isArchived; @@ -28,7 +28,7 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings public TrackedEventPreference(TrackedEventPreference other) { this(); eventId.setValue(other.getEventId()); - regattaId.setValue(other.getRegattaId()); + leaderboardName.setValue(other.getLeaderboardName()); trackedElements.setValues(other.getTrackedElements()); baseUrl.setValue(other.getBaseUrl()); isArchived.setValue(other.getIsArchived()); @@ -38,7 +38,7 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings public TrackedEventPreference(TrackedEventPreference other, boolean isArchived) { this(); eventId.setValue(other.getEventId()); - regattaId.setValue(other.getRegattaId()); + leaderboardName.setValue(other.getLeaderboardName()); trackedElements.setValues(other.getTrackedElements()); baseUrl.setValue(other.getBaseUrl()); this.isArchived.setValue(isArchived); @@ -48,7 +48,7 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings public TrackedEventPreference(TrackedEventPreference other, TrackedElementWithDeviceId trackedElement) { this(); eventId.setValue(other.getEventId()); - regattaId.setValue(other.getRegattaId()); + leaderboardName.setValue(other.getLeaderboardName()); final Collection trackedElements = new HashSet<>(); Util.addAll(other.getTrackedElements(), trackedElements); trackedElements.add(trackedElement); @@ -57,11 +57,11 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings this.isArchived.setValue(other.getIsArchived()); } - public TrackedEventPreference(UUID eventId, String regattaId, Iterable trackedElements, - String baseUrl, boolean isArchived) { + public TrackedEventPreference(UUID eventId, String leaderboardName, + Iterable trackedElements, String baseUrl, boolean isArchived) { this(); this.eventId.setValue(eventId); - this.regattaId.setValue(regattaId); + this.leaderboardName.setValue(leaderboardName); this.trackedElements.setValues(trackedElements); this.baseUrl.setValue(baseUrl); this.isArchived.setValue(isArchived); @@ -70,7 +70,7 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings @Override protected void addChildSettings() { eventId = new UUIDSetting("eventId", this); - regattaId = new StringSetting("regattaId", this); + leaderboardName = new StringSetting("leaderboardName", this); trackedElements = new SettingsList("trackedElements", this, () -> new TrackedElementWithDeviceId()); baseUrl = new StringSetting("baseUrl", this); @@ -81,8 +81,8 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings return eventId.getValue(); } - public String getRegattaId() { - return regattaId.getValue(); + public String getLeaderboardName() { + return leaderboardName.getValue(); } public Iterable getTrackedElements() { From 6877b4b6f55b8dbd09abb6f9f60f128d16a48d6f Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Wed, 26 Jun 2019 14:58:41 +0200 Subject: [PATCH 39/69] Bug 4960: regatta secret is now also stored --- .../selenium/api/event/TrackedEventsApi.java | 10 +++- .../test/TrackedEventsResourceApiTest.java | 52 ++++++++++++------- .../jaxrs/api/TrackedEventsResource.java | 39 ++++++-------- .../model/TrackedEventPreference.java | 13 ++++- 4 files changed, 67 insertions(+), 47 deletions(-) diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java index 615fdb9fb35..d18323d27f1 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java @@ -24,6 +24,7 @@ public class TrackedEventsApi { private static final String KEY_EVENT_END = "end"; private static final String KEY_EVENT_BASE_URL = "url"; private static final String KEY_EVENT_IS_OWNER = "isOwner"; + private static final String KEY_EVENT_REGATTA_SECRET = "regattaSecret"; private static final String KEY_EVENT_TRACKED_ELEMENTS = "trackedElements"; @@ -40,8 +41,8 @@ public class TrackedEventsApi { return new TrackedEvents(ctx.get(TRACKED_EVENTS_URL, queryParams)); } - public void updateTrackedEvent(ApiContext ctx, String eventId, String leaderboardName, String eventBaseUrl, - String deviceId, String competitorId, String boatId, String markId) { + public void updateOrCreateTrackedEvent(ApiContext ctx, String eventId, String leaderboardName, String eventBaseUrl, + String deviceId, String competitorId, String boatId, String markId, String regattaSecret) { final JSONObject json = new JSONObject(); json.put(KEY_EVENT_ID, eventId); json.put(KEY_LEADERBOARD_NAME, leaderboardName); @@ -59,6 +60,7 @@ public class TrackedEventsApi { } elements.add(elem); + json.put(KEY_EVENT_REGATTA_SECRET, regattaSecret); json.put(KEY_EVENT_TRACKED_ELEMENTS, elements); json.put(KEY_EVENT_IS_ARCHIVED, false); ctx.put(TRACKED_EVENTS_URL, new HashMap<>(), json); @@ -160,6 +162,10 @@ public class TrackedEventsApi { public String getLeaderboardName() { return get(KEY_LEADERBOARD_NAME); } + + public String getRegattaSecret() { + return get(KEY_EVENT_REGATTA_SECRET); + } } } diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java index 4a2d32dfa2c..c0be354677e 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java @@ -53,18 +53,20 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { "75QMNATIONALEKREUZER", CompetitorRegistrationType.CLOSED, "Mannheim"); final String eventId = evt.getId(); final String leaderboardName = evt.getName(); + final String regattaSecret = evt.getSecret(); final Event evt2 = eventApi.createEvent(adminCtx, "TestEvent-" + UUID.randomUUID().toString(), "75QMNATIONALEKREUZER", CompetitorRegistrationType.CLOSED, "Mannheim"); final String eventId2 = evt2.getId(); final String leaderboardName2 = evt2.getName(); + final String regattaSecret2 = evt.getSecret(); - trackedEventsApi.updateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, competitorId, - null, null); - trackedEventsApi.updateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, null, boatId, - null); - trackedEventsApi.updateTrackedEvent(adminCtx, eventId2, leaderboardName2, eventBaseUrl, deviceId, null, null, - markId); + trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, + competitorId, null, null, regattaSecret); + trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, null, + boatId, null, regattaSecret); + trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, eventId2, leaderboardName2, eventBaseUrl, deviceId, null, + null, markId, regattaSecret2); trackedEventsApi.setArchived(adminCtx, evt.getId(), true); trackedEventsApi.setArchived(adminCtx, evt2.getId(), false); @@ -78,10 +80,12 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { if (eventId.equals(event.getEventId())) { Assert.assertEquals("Unexpected event ID", eventId, event.getEventId()); Assert.assertEquals("Unexpected leaderboard name", leaderboardName, event.getLeaderboardName()); + Assert.assertEquals("Unexpected regatta secret", regattaSecret, event.getRegattaSecret()); Assert.fail("Expected event 1 to not be shown anymore."); } else if (eventId2.equals(event.getEventId())) { Assert.assertEquals("Unexpected event ID", eventId2, event.getEventId()); Assert.assertEquals("Unexpected leaderboard name", leaderboardName2, event.getLeaderboardName()); + Assert.assertEquals("Unexpected regatta secret", regattaSecret2, event.getRegattaSecret()); } else { Assert.fail("Invalid event id."); } @@ -117,18 +121,20 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { "75QMNATIONALEKREUZER", CompetitorRegistrationType.CLOSED, "Mannheim"); final String eventId = evt.getId(); final String leaderboardName = evt.getName(); + final String regattaSecret = evt.getSecret(); final Event evt2 = eventApi.createEvent(adminCtx, "TestEvent-" + UUID.randomUUID().toString(), "75QMNATIONALEKREUZER", CompetitorRegistrationType.CLOSED, "Mannheim"); final String eventId2 = evt2.getId(); final String leaderboardName2 = evt2.getName(); + final String regattaSecret2 = evt2.getSecret(); - trackedEventsApi.updateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, competitorId, - null, null); - trackedEventsApi.updateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, null, boatId, - null); - trackedEventsApi.updateTrackedEvent(adminCtx, eventId2, leaderboardName2, eventBaseUrl, deviceId, null, null, - markId); + trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, + competitorId, null, null, regattaSecret); + trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, null, + boatId, null, regattaSecret); + trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, eventId2, leaderboardName2, eventBaseUrl, deviceId, null, + null, markId, regattaSecret2); // check if created event is still there final TrackedEvents trackedEvents = trackedEventsApi.getTrackedEvents(adminCtx, true); @@ -140,9 +146,11 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { if (eventId.equals(event.getEventId())) { Assert.assertEquals("Unexpected event ID", eventId, event.getEventId()); Assert.assertEquals("Unexpected leaderboard name", leaderboardName, event.getLeaderboardName()); + Assert.assertEquals("Unexpected regatta secret", regattaSecret, event.getRegattaSecret()); } else if (eventId2.equals(event.getEventId())) { Assert.assertEquals("Unexpected event ID", eventId2, event.getEventId()); Assert.assertEquals("Unexpected leaderboard name", leaderboardName2, event.getLeaderboardName()); + Assert.assertEquals("Unexpected regatta secret", regattaSecret2, event.getRegattaSecret()); } else { Assert.fail("Invalid event id."); } @@ -180,13 +188,14 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { CompetitorRegistrationType.CLOSED, "Mannheim"); final String eventId = evt.getId(); final String leaderboardName = evt.getName(); + final String regattaSecret = evt.getSecret(); - trackedEventsApi.updateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, competitorId, - null, null); - trackedEventsApi.updateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, null, boatId, - null); - trackedEventsApi.updateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, null, null, - markId); + trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, + competitorId, null, null, regattaSecret); + trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, null, + boatId, null, regattaSecret); + trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, null, + null, markId, regattaSecret); // check if created event is still there final TrackedEvents trackedEvents = trackedEventsApi.getTrackedEvents(adminCtx, true); @@ -197,6 +206,7 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { Assert.assertEquals("Unexpected event base url", eventBaseUrl, event.getEventBaseUrl()); Assert.assertEquals("Unexpected event ID", eventId, event.getEventId()); Assert.assertEquals("Unexpected leaderboard name", leaderboardName, event.getLeaderboardName()); + Assert.assertEquals("Unexpected regatta secret", regattaSecret, event.getRegattaSecret()); int cntElements = 0; for (final TrackedElement elem : event.getTrackedElements()) { @@ -245,9 +255,10 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { CompetitorRegistrationType.CLOSED, "Mannheim"); final String eventId = evt.getId(); final String leaderboardName = evt.getName(); + final String regattaSecret = evt.getSecret(); - trackedEventsApi.updateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, competitorId, - boatId, markId); + trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, + competitorId, boatId, markId, regattaSecret); // check if created event is still there final TrackedEvents trackedEvents = trackedEventsApi.getTrackedEvents(adminCtx, true); @@ -258,6 +269,7 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { Assert.assertEquals("Unexpected event base url", eventBaseUrl, event.getEventBaseUrl()); Assert.assertEquals("Unexpected event ID", eventId, event.getEventId()); Assert.assertEquals("Unexpected leaderboard name", leaderboardName, event.getLeaderboardName()); + Assert.assertEquals("Unexpected regatta secret", regattaSecret, event.getRegattaSecret()); boolean hasElements = false; for (final TrackedElement elem : event.getTrackedElements()) { diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index aa270a83cd6..f261887d149 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -56,6 +56,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { private static final String KEY_EVENT_BASE_URL = "url"; private static final String KEY_EVENT_IS_OWNER = "isOwner"; private static final String KEY_EVENT_IMAGE_URL = "imageUrl"; + private static final String KEY_EVENT_REGATTA_SECRET = "regattaSecret"; private static final String KEY_TRACKED_ELEMENT_DEVICE_ID = "deviceId"; private static final String KEY_TRACKED_ELEMENT_COMPETITOR_ID = "competitorId"; private static final String KEY_TRACKED_ELEMENT_BOAT_ID = "boatId"; @@ -91,45 +92,33 @@ public class TrackedEventsResource extends AbstractSailingServerResource { final UUID eventId = pref.getEventId(); final Event event = getService().getEvent(eventId); if (event != null) { + // event actually exists -> parse relevant data + final JSONObject jsonEvent = new JSONObject(); if (getSecurityService().hasCurrentUserReadPermission(event)) { - // event actually exists -> parse relevant data + // user has read permission on event -> add additional event-specific data final OwnershipAnnotation ownership = getSecurityService() .getOwnership(event.getIdentifier()); final boolean isOwner = currentUser == null ? false : currentUser.equals(ownership.getAnnotation().getUserOwner()); + jsonEvent.put(KEY_EVENT_IS_OWNER, isOwner); - final JSONObject jsonEvent = new JSONObject(); - jsonEvent.put(KEY_EVENT_ID, event.getId().toString()); jsonEvent.put(KEY_EVENT_NAME, event.getName()); jsonEvent.put(KEY_EVENT_START, event.getStartDate().toString()); jsonEvent.put(KEY_EVENT_AND, event.getEndDate().toString()); - jsonEvent.put(KEY_EVENT_TRACKED_ELEMENTS, trackedElementsToJson(pref)); final List imageWithLogoTag = event .findImagesWithTag(MediaTagConstants.LOGO.getName()); if (!imageWithLogoTag.isEmpty()) { jsonEvent.put(KEY_EVENT_IMAGE_URL, imageWithLogoTag.get(0).getURL().toExternalForm()); } - jsonEvent.put(KEY_EVENT_BASE_URL, pref.getBaseUrl()); - jsonEvent.put(KEY_EVENT_IS_ARCHIVED, pref.getIsArchived()); - jsonEvent.put(KEY_EVENT_IS_OWNER, isOwner); - jsonEvent.put(KEY_LEADERBOARD_NAME, pref.getLeaderboardName()); - result.add(jsonEvent); - } else { - // User does not have read permission on event - final JSONObject jsonEvent = new JSONObject(); - jsonEvent.put(KEY_EVENT_ID, pref.getEventId()); - jsonEvent.put(KEY_LEADERBOARD_NAME, pref.getLeaderboardName()); - final List imageWithLogoTag = event - .findImagesWithTag(MediaTagConstants.LOGO.getName()); - if (!imageWithLogoTag.isEmpty()) { - jsonEvent.put(KEY_EVENT_IMAGE_URL, imageWithLogoTag.get(0).getURL().toExternalForm()); - } - jsonEvent.put(KEY_EVENT_BASE_URL, pref.getBaseUrl()); - jsonEvent.put(KEY_EVENT_IS_ARCHIVED, pref.getIsArchived()); - jsonEvent.put(KEY_EVENT_TRACKED_ELEMENTS, trackedElementsToJson(pref)); - result.add(jsonEvent); } + jsonEvent.put(KEY_EVENT_ID, pref.getEventId().toString()); + jsonEvent.put(KEY_EVENT_REGATTA_SECRET, pref.getRegattaSecret()); + jsonEvent.put(KEY_EVENT_BASE_URL, pref.getBaseUrl()); + jsonEvent.put(KEY_EVENT_IS_ARCHIVED, pref.getIsArchived()); + jsonEvent.put(KEY_LEADERBOARD_NAME, pref.getLeaderboardName()); + jsonEvent.put(KEY_EVENT_TRACKED_ELEMENTS, trackedElementsToJson(pref)); + result.add(jsonEvent); } else { // TODO: // check, if base url is equal to this server, if not, event might be on different server @@ -181,6 +170,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { final String leaderboardName = (String) requestObject.get(KEY_LEADERBOARD_NAME); final Boolean archived = (Boolean) requestObject.get(KEY_EVENT_IS_ARCHIVED); final String baseUrl = (String) requestObject.get(KEY_EVENT_BASE_URL); + final String regattaSecret = (String) requestObject.get(KEY_EVENT_REGATTA_SECRET); try { final UUID uuidEvent = UUID.fromString(eventId); final boolean isArchived = archived; @@ -267,7 +257,8 @@ public class TrackedEventsResource extends AbstractSailingServerResource { if (!eventContained) { // event was not found, create a new tracked event final TrackedEventPreference newPreference = new TrackedEventPreference(uuidEvent, - leaderboardName, Arrays.asList(newPrefElem), baseUrl, isArchived); + leaderboardName, Arrays.asList(newPrefElem), baseUrl, isArchived, + regattaSecret); prefsNew.add(newPreference); } diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java index 96b828caaba..b91e26c82d1 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreference.java @@ -18,6 +18,7 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings private transient StringSetting leaderboardName; private transient StringSetting baseUrl; private transient BooleanSetting isArchived; + private transient StringSetting regattaSecret; private transient SettingsList trackedElements; @@ -32,6 +33,7 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings trackedElements.setValues(other.getTrackedElements()); baseUrl.setValue(other.getBaseUrl()); isArchived.setValue(other.getIsArchived()); + this.regattaSecret.setValue(other.getRegattaSecret()); } /** copy constructor with new archived state */ @@ -42,6 +44,7 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings trackedElements.setValues(other.getTrackedElements()); baseUrl.setValue(other.getBaseUrl()); this.isArchived.setValue(isArchived); + this.regattaSecret.setValue(other.getRegattaSecret()); } /** copy constructor with additional tracked event */ @@ -55,16 +58,19 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings this.trackedElements.setValues(trackedElements); baseUrl.setValue(other.getBaseUrl()); this.isArchived.setValue(other.getIsArchived()); + this.regattaSecret.setValue(other.getRegattaSecret()); } public TrackedEventPreference(UUID eventId, String leaderboardName, - Iterable trackedElements, String baseUrl, boolean isArchived) { + Iterable trackedElements, String baseUrl, boolean isArchived, + String regattaSecret) { this(); this.eventId.setValue(eventId); this.leaderboardName.setValue(leaderboardName); this.trackedElements.setValues(trackedElements); this.baseUrl.setValue(baseUrl); this.isArchived.setValue(isArchived); + this.regattaSecret.setValue(regattaSecret); } @Override @@ -75,6 +81,7 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings () -> new TrackedElementWithDeviceId()); baseUrl = new StringSetting("baseUrl", this); isArchived = new BooleanSetting("isArchived", this); + regattaSecret = new StringSetting("regattaSecret", this); } public UUID getEventId() { @@ -96,4 +103,8 @@ public class TrackedEventPreference extends AbstractGenericSerializableSettings public boolean getIsArchived() { return isArchived.getValue(); } + + public String getRegattaSecret() { + return regattaSecret.getValue(); + } } From e889d65f022012150c36ac4fe82e3d3fd5b7c6b7 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Wed, 26 Jun 2019 15:19:23 +0200 Subject: [PATCH 40/69] Bug 4960: added leaderboardName as second parameter next to eventId and used path parameters --- .../selenium/api/event/TrackedEventsApi.java | 11 ++++---- .../test/TrackedEventsResourceApiTest.java | 9 ++++--- .../jaxrs/api/TrackedEventsResource.java | 25 +++++++++++-------- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java index d18323d27f1..ff8e9eaed67 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java @@ -44,8 +44,6 @@ public class TrackedEventsApi { public void updateOrCreateTrackedEvent(ApiContext ctx, String eventId, String leaderboardName, String eventBaseUrl, String deviceId, String competitorId, String boatId, String markId, String regattaSecret) { final JSONObject json = new JSONObject(); - json.put(KEY_EVENT_ID, eventId); - json.put(KEY_LEADERBOARD_NAME, leaderboardName); json.put(KEY_EVENT_BASE_URL, eventBaseUrl); final JSONArray elements = new JSONArray(); @@ -63,18 +61,19 @@ public class TrackedEventsApi { json.put(KEY_EVENT_REGATTA_SECRET, regattaSecret); json.put(KEY_EVENT_TRACKED_ELEMENTS, elements); json.put(KEY_EVENT_IS_ARCHIVED, false); - ctx.put(TRACKED_EVENTS_URL, new HashMap<>(), json); + ctx.put(TRACKED_EVENTS_URL + eventId + "/" + leaderboardName, new HashMap<>(), json); } - public void setArchived(ApiContext ctx, String eventId, boolean archived) { + public void setArchived(ApiContext ctx, String eventId, String leaderboardName, boolean archived) { final HashMap queryParams = new HashMap<>(); queryParams.put(KEY_EVENT_ID, eventId); + queryParams.put(KEY_LEADERBOARD_NAME, leaderboardName); queryParams.put(KEY_QUERY_INCLUDE_ARCHIVED, Boolean.toString(archived)); ctx.post(TRACKED_EVENTS_URL, queryParams); } - public void deleteEventTrackings(ApiContext ctx, String eventId) { - ctx.delete(TRACKED_EVENTS_URL + eventId); + public void deleteEventTrackings(ApiContext ctx, String eventId, String leaderboardName) { + ctx.delete(TRACKED_EVENTS_URL + eventId + "/" + leaderboardName); } public class TrackedElement extends JsonWrapper { diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java index c0be354677e..c0dcfcd7c49 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java @@ -68,8 +68,8 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, eventId2, leaderboardName2, eventBaseUrl, deviceId, null, null, markId, regattaSecret2); - trackedEventsApi.setArchived(adminCtx, evt.getId(), true); - trackedEventsApi.setArchived(adminCtx, evt2.getId(), false); + trackedEventsApi.setArchived(adminCtx, evt.getId(), leaderboardName, true); + trackedEventsApi.setArchived(adminCtx, evt2.getId(), leaderboardName2, false); // check if created event is still there final TrackedEvents trackedEvents = trackedEventsApi.getTrackedEvents(adminCtx, false); @@ -289,10 +289,11 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { @Test public void testDeleteEvent() { final ApiContext adminCtx = createAdminApiContext(getContextRoot(), SERVER_CONTEXT); + final String leaderboardName = "TestEvent-" + UUID.randomUUID().toString(); final String eventId = testCreateTrackedEventWithTracking(UUID.randomUUID().toString(), null, null, adminCtx, - "TestEvent-" + UUID.randomUUID().toString()); + leaderboardName); - trackedEventsApi.deleteEventTrackings(adminCtx, eventId); + trackedEventsApi.deleteEventTrackings(adminCtx, eventId, leaderboardName); final TrackedEvents trackedEvents = trackedEventsApi.getTrackedEvents(adminCtx, true); Assert.assertNotNull("Tracked Events element should not be null", trackedEvents); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index f261887d149..aa516bbf9d3 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -51,7 +51,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { private static final String KEY_EVENT_IS_ARCHIVED = "isArchived"; private static final String KEY_EVENT_NAME = "name"; private static final String KEY_EVENT_START = "start"; - private static final String KEY_EVENT_AND = "end"; + private static final String KEY_EVENT_END = "end"; private static final String KEY_EVENT_TRACKED_ELEMENTS = "trackedElements"; private static final String KEY_EVENT_BASE_URL = "url"; private static final String KEY_EVENT_IS_OWNER = "isOwner"; @@ -104,7 +104,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { jsonEvent.put(KEY_EVENT_NAME, event.getName()); jsonEvent.put(KEY_EVENT_START, event.getStartDate().toString()); - jsonEvent.put(KEY_EVENT_AND, event.getEndDate().toString()); + jsonEvent.put(KEY_EVENT_END, event.getEndDate().toString()); final List imageWithLogoTag = event .findImagesWithTag(MediaTagConstants.LOGO.getName()); @@ -157,7 +157,9 @@ public class TrackedEventsResource extends AbstractSailingServerResource { @PUT @Consumes(MediaType.APPLICATION_JSON) - public Response updateOrCreateTrackedEvent(String jsonBody) { + @Path("{eventId}/{leaderboardName}") + public Response updateOrCreateTrackedEvent(@PathParam(KEY_EVENT_ID) String eventId, + @PathParam(KEY_LEADERBOARD_NAME) String leaderboardName, String jsonBody) { ResponseBuilder responseBuilder = null; final User currentUser = getSecurityService().getCurrentUser(); @@ -166,8 +168,6 @@ public class TrackedEventsResource extends AbstractSailingServerResource { try { final Object requestBody = JSONValue.parseWithException(jsonBody); final JSONObject requestObject = Helpers.toJSONObjectSafe(requestBody); - final String eventId = (String) requestObject.get(KEY_EVENT_ID); - final String leaderboardName = (String) requestObject.get(KEY_LEADERBOARD_NAME); final Boolean archived = (Boolean) requestObject.get(KEY_EVENT_IS_ARCHIVED); final String baseUrl = (String) requestObject.get(KEY_EVENT_BASE_URL); final String regattaSecret = (String) requestObject.get(KEY_EVENT_REGATTA_SECRET); @@ -301,19 +301,22 @@ public class TrackedEventsResource extends AbstractSailingServerResource { @POST public Response updateTrackedEventsArchivedStatus(@QueryParam(KEY_EVENT_ID) String eventId, + @QueryParam(KEY_LEADERBOARD_NAME) String leaderboardName, @QueryParam(KEY_QUERY_INCLUDE_ARCHIVED) String archived) { final boolean isArchived = Boolean.parseBoolean(archived); - return applyOnEventById(eventId, pref -> new TrackedEventPreference(pref, isArchived)); + return applyOnEventByIdAndLeadboardName(eventId, leaderboardName, + pref -> new TrackedEventPreference(pref, isArchived)); } @DELETE - @Path("{eventId}") - public Response deleteTrackedEvents(@PathParam(KEY_EVENT_ID) String eventId) { - return applyOnEventById(eventId, pref -> null); + @Path("{eventId}/{leaderboardName}") + public Response deleteTrackedEvents(@PathParam(KEY_EVENT_ID) String eventId, + @PathParam(KEY_LEADERBOARD_NAME) String leaderboardName) { + return applyOnEventByIdAndLeadboardName(eventId, leaderboardName, pref -> null); } /** Finds the tracked event with the corresponding eventId and applies the function to it. */ - private Response applyOnEventById(String eventId, + private Response applyOnEventByIdAndLeadboardName(String eventId, String leaderboardName, Function function) { ResponseBuilder responseBuilder; final User currentUser = getSecurityService().getCurrentUser(); @@ -336,7 +339,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { boolean found = false; final Collection newPrefs = new HashSet<>(); for (final TrackedEventPreference pref : prefs.getTrackedEvents()) { - if (pref.getEventId().equals(eventUuid)) { + if (pref.getEventId().equals(eventUuid) && pref.getLeaderboardName().equals(leaderboardName)) { // tracked event found, apply function on it and remove it if result of function execution // is null found = true; From ff73da6c23c5ebec20ffcd7030b661c486715158 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Wed, 26 Jun 2019 15:32:16 +0200 Subject: [PATCH 41/69] Bug 4960: moved TrackedEventsResource from /api/v1/events/trackedevents to /api/v1/trackedevents --- .../com/sap/sailing/selenium/api/event/TrackedEventsApi.java | 2 +- .../sailing/server/gateway/jaxrs/api/TrackedEventsResource.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java index ff8e9eaed67..ea032938cd5 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java @@ -13,7 +13,7 @@ import com.sap.sailing.selenium.api.core.JsonWrapper; public class TrackedEventsApi { - private static final String TRACKED_EVENTS_URL = "/api/v1/events/trackedevents/"; + private static final String TRACKED_EVENTS_URL = "/api/v1/trackedevents/"; private static final String KEY_TRACKED_EVENTS = "trackedEvents"; private static final String KEY_LEADERBOARD_NAME = "leaderboardName"; diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index aa516bbf9d3..bc722d41c17 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -41,7 +41,7 @@ import com.sap.sse.security.shared.OwnershipAnnotation; import com.sap.sse.security.shared.impl.User; import com.sap.sse.shared.media.ImageDescriptor; -@Path("/v1/events/trackedevents/") +@Path("/v1/trackedevents/") public class TrackedEventsResource extends AbstractSailingServerResource { private static final String KEY_QUERY_INCLUDE_ARCHIVED = "includeArchived"; From 4b7daa1800983d65533053a4cbbcc962c07892d6 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Wed, 26 Jun 2019 16:24:12 +0200 Subject: [PATCH 42/69] Bug 4960: added documentation for retrieving tracked events via REST API endpoint --- .../webservices/api/v1/index.html | 4 ++ .../api/v1/trackedeventsGetDoc.html | 53 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 java/com.sap.sailing.server.gateway/webservices/api/v1/trackedeventsGetDoc.html diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html index b36bfcfac64..434a7cd85be 100644 --- a/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html @@ -340,6 +340,10 @@ name to make sure you get to the event you're interested in. /api/v1/status Returns a status description for the "RacingEventService" core service + + /api/v1/trackedevents + Gets all tracked events with the associated device-to-competitor/boat/mark elements for the current user. +
diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/trackedeventsGetDoc.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/trackedeventsGetDoc.html new file mode 100644 index 00000000000..99e065311df --- /dev/null +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/trackedeventsGetDoc.html @@ -0,0 +1,53 @@ + + + + + + + +SAP Sailing Analytics Webservices API Version 1.0 + + +

SAP Sailing Analytics Webservices API Version 1.0

+

URL: /api/v1/trackedevents

+ + Description: +

Gets all tracked events with the associated + device-to-competitor/boat/mark elements for the current user.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Webservice Type:REST
Output format:Json
Mandatory parameters:includeArchived: Should be set to true, if the archived + elements should be returned as well. Default value false returns + only non-archived elements.
Optional parameters:None
Request method:GET
Example:http://www.sapsailing.com/sailingserver/api/v1/trackedevents?includeArchived=false
+ Status 200
+
+ Back to Web Service Overview + + From 5ac3faff2073c588ec7435190fc7cedcccb3c0b0 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Wed, 26 Jun 2019 16:24:51 +0200 Subject: [PATCH 43/69] Bug 4960: added documentation for creating or updating a tracked event via REST API endpoint --- .../webservices/api/v1/index.html | 4 ++ .../api/v1/trackedeventsPutDoc.html | 58 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 java/com.sap.sailing.server.gateway/webservices/api/v1/trackedeventsPutDoc.html diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html index 434a7cd85be..1919cc9f643 100644 --- a/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html @@ -344,6 +344,10 @@ name to make sure you get to the event you're interested in. /api/v1/trackedevents Gets all tracked events with the associated device-to-competitor/boat/mark elements for the current user. + + /api/v1/trackedevents + Create or update a tracked event for the current user. +
diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/trackedeventsPutDoc.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/trackedeventsPutDoc.html new file mode 100644 index 00000000000..47ca142ee3e --- /dev/null +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/trackedeventsPutDoc.html @@ -0,0 +1,58 @@ + + + + + + + +SAP Sailing Analytics Webservices API Version 1.0 + + +

SAP Sailing Analytics Webservices API Version 1.0

+

URL: /api/v1/trackedevents/{eventId}/{leaderboardName}

+ + Description: +

Create or update a tracked event for the current user.

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Webservice Type:REST
Output format:Json
Mandatory parameters:Path Parameter eventId: Identifier of the associated event
+ Path Parameter leaderboardName: Name of the associated leaderboard +
Optional parameters:None
Request method:PUT
Example:Request: + http://www.sapsailing.com/sailingserver/api/v1/trackedevents/61fe232b-19b8-455f-ac91-23a53a5c557a/TestRegattaLeaderboard
+
Body (device-to-competitor):
+ {"url":"http://www.sapsailing.com","regattaSecret":"71fe232b-19b8-455f-ac91-23a53a5c557a","trackedElements":[{"deviceId":"301eda00-68ad-402d-9734-4a7d5b8df406","competitorId":"6204e6d2-2d6c-4891-b077-d83117c69513"}],"isArchived":false}
+
Body(device-to-boat):
+ {"url":"http://www.sapsailing.com","regattaSecret":"71fe232b-19b8-455f-ac91-23a53a5c557a","trackedElements":[{"deviceId":"301eda00-68ad-402d-9734-4a7d5b8df406","boatId":"6204e6d2-2d6c-4891-b077-d83117c69513"}],"isArchived":false}
+
Body (device-to-mark):
+ {"url":"http://www.sapsailing.com","regattaSecret":"71fe232b-19b8-455f-ac91-23a53a5c557a","trackedElements":[{"deviceId":"301eda00-68ad-402d-9734-4a7d5b8df406","markId":"6204e6d2-2d6c-4891-b077-d83117c69513"}],"isArchived":false}
+ Status 202
+
+
+ Back to Web Service Overview + + From 67ed93b1e6b2be73e35868ecfcf19c1841d0ef13 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Wed, 26 Jun 2019 16:25:16 +0200 Subject: [PATCH 44/69] Bug 4960: added documentation for deleting a tracked event via REST API endpoint --- .../webservices/api/v1/index.html | 4 ++ .../api/v1/trackedeventsDeleteDoc.html | 52 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 java/com.sap.sailing.server.gateway/webservices/api/v1/trackedeventsDeleteDoc.html diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html index 1919cc9f643..12bcf454e79 100644 --- a/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html @@ -348,6 +348,10 @@ name to make sure you get to the event you're interested in. /api/v1/trackedevents Create or update a tracked event for the current user. + + /api/v1/trackedevents + Delete a tracked event for the current user. +
diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/trackedeventsDeleteDoc.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/trackedeventsDeleteDoc.html new file mode 100644 index 00000000000..e9c169db61c --- /dev/null +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/trackedeventsDeleteDoc.html @@ -0,0 +1,52 @@ + + + + + + + +SAP Sailing Analytics Webservices API Version 1.0 + + +

SAP Sailing Analytics Webservices API Version 1.0

+

URL: /api/v1/trackedevents/{eventId}/{leaderboardName}

+ + Description: +

Delete a tracked event for the current user.

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Webservice Type:REST
Output format:Json
Mandatory parameters:Path parameter eventId: Identifier of the associated event
+ Path parameter leaderboardName: Name of the associated leaderboard +
Optional parameters:None
Request method:DELETE
Example:Request: + http://www.sapsailing.com/sailingserver/api/v1/trackedevents?eventId=71fe232b-19b8-455f-ac91-23a53a5c557a&leaderbaordName=TestRegattaLeaderboard
+ Status 202
+
+
+ Back to Web Service Overview + + From 8eb24830e1623d520a732d7d0dfb10f99e4e9ef9 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Wed, 26 Jun 2019 16:25:32 +0200 Subject: [PATCH 45/69] Bug 4960: added documentation for updating the is-archived state of a tracked event via REST API endpoint --- .../webservices/api/v1/index.html | 4 ++ .../api/v1/trackedeventsPostDoc.html | 55 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 java/com.sap.sailing.server.gateway/webservices/api/v1/trackedeventsPostDoc.html diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html index 12bcf454e79..779e4b0dfe6 100644 --- a/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html @@ -348,6 +348,10 @@ name to make sure you get to the event you're interested in. /api/v1/trackedevents Create or update a tracked event for the current user. + + /api/v1/trackedevents + Update the archived status of a tracked event for the current user. + /api/v1/trackedevents Delete a tracked event for the current user. diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/trackedeventsPostDoc.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/trackedeventsPostDoc.html new file mode 100644 index 00000000000..bf9b0f574a2 --- /dev/null +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/trackedeventsPostDoc.html @@ -0,0 +1,55 @@ + + + + + + + +SAP Sailing Analytics Webservices API Version 1.0 + + +

SAP Sailing Analytics Webservices API Version 1.0

+

URL: /api/v1/trackedevents

+ + Description: +

Update the archived status of a tracked event for the current + user.

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Webservice Type:REST
Output format:Json
Mandatory parameters:eventId: Identifier of the associated event
+ leaderboardName: Name of the associated leaderboard
+ isArchived: True or False depending on whether the event should be + set to archived or non-archived. +
Optional parameters:None
Request method:POST
Example:Request: + http://www.sapsailing.com/sailingserver/api/v1/trackedevents?eventId=71fe232b-19b8-455f-ac91-23a53a5c557a&leaderbaordName=TestRegattaLeaderboard
+ Status 202
+
+
+ Back to Web Service Overview + + From 71263799f3eceaba13e8a0d8ee8d6e0a05b720f5 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Wed, 26 Jun 2019 16:31:54 +0200 Subject: [PATCH 46/69] Bug 4960: added release notes for new trackedevents end points --- java/com.sap.sailing.www/release_notes_admin.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/java/com.sap.sailing.www/release_notes_admin.html b/java/com.sap.sailing.www/release_notes_admin.html index ff2b228393d..8ca90a396d1 100755 --- a/java/com.sap.sailing.www/release_notes_admin.html +++ b/java/com.sap.sailing.www/release_notes_admin.html @@ -29,6 +29,10 @@ The new end points support resolving, creation and deletion of user groups, as well as adding and removing users and roles to and from user groups. +
  • A couple of new API end points for managing tracked events were added under /api/v1/trackedevents/. + The new end points support creation, reading, updating and deleting tracked events and their + associated device-competitor/boat/mark elements for the current user. +
  • May 2019

      From 245c136fba50c0f3baef5ad67c74319950e30fb4 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Wed, 26 Jun 2019 16:58:44 +0200 Subject: [PATCH 47/69] Bug 4960: added selenium test which tests TRackedEventResource api end points with multiple users --- .../test/TrackedEventsResourceApiTest.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java index c0dcfcd7c49..01720a38bdc 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java @@ -2,6 +2,7 @@ package com.sap.sailing.selenium.api.test; import static com.sap.sailing.selenium.api.core.ApiContext.SERVER_CONTEXT; import static com.sap.sailing.selenium.api.core.ApiContext.createAdminApiContext; +import static com.sap.sailing.selenium.api.core.ApiContext.createApiContext; import java.util.UUID; @@ -13,6 +14,7 @@ import com.sap.sailing.domain.common.CompetitorRegistrationType; import com.sap.sailing.selenium.api.core.ApiContext; import com.sap.sailing.selenium.api.event.EventApi; import com.sap.sailing.selenium.api.event.EventApi.Event; +import com.sap.sailing.selenium.api.event.SecurityApi; import com.sap.sailing.selenium.api.event.TrackedEventsApi; import com.sap.sailing.selenium.api.event.TrackedEventsApi.TrackedElement; import com.sap.sailing.selenium.api.event.TrackedEventsApi.TrackedEvent; @@ -25,6 +27,7 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { private final TrackedEventsApi trackedEventsApi = new TrackedEventsApi(); private final EventApi eventApi = new EventApi(); + private final SecurityApi securityApi = new SecurityApi(); @Before public void setUp() { @@ -300,4 +303,24 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { Assert.assertTrue("Expected empty list of tracked events", Util.isEmpty(trackedEvents.getEvents())); } + @Test + public void testMultipleUsers() { + + // create test user + final ApiContext adminSecurityCtx = createAdminApiContext(getContextRoot(), ApiContext.SECURITY_CONTEXT); + securityApi.createUser(adminSecurityCtx, "tuser", "Test User", null, "testuser"); + final ApiContext userCtx = createApiContext(getContextRoot(), SERVER_CONTEXT, "tuser", "testuser"); + + final ApiContext adminCtx = createAdminApiContext(getContextRoot(), SERVER_CONTEXT); + + // add an event in the user context of admin user + testCreateTrackedEventWithTracking(null, UUID.randomUUID().toString(), null, adminCtx, + "TestEvent-" + UUID.randomUUID().toString()); + + // check if event is invisible to the other user + final TrackedEvents trackedEvents = trackedEventsApi.getTrackedEvents(userCtx, true); + Assert.assertNotNull("Tracked Events element should not be null", trackedEvents); + Assert.assertTrue("Expected empty list of tracked events", Util.isEmpty(trackedEvents.getEvents())); + } + } From d0a45d2c2343a5a7d53f038f386bbaacc32ea911 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Thu, 27 Jun 2019 15:00:14 +0200 Subject: [PATCH 48/69] Bug 4960: moved initialization of child settings for TrackedElementWithDeviceId from constructor into addChildSettings --- .../model/TrackedElementWithDeviceId.java | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedElementWithDeviceId.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedElementWithDeviceId.java index 0700cc75623..aea9b17eb8c 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedElementWithDeviceId.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedElementWithDeviceId.java @@ -16,10 +16,6 @@ public class TrackedElementWithDeviceId extends AbstractGenericSerializableSetti private transient UUIDSetting trackedMarkId; public TrackedElementWithDeviceId() { - deviceId = new StringSetting("deviceId", this); - trackedCompetitorId = new UUIDSetting("trackedCompetitorId", this); - trackedBoatId = new UUIDSetting("trackedBoatId", this); - trackedMarkId = new UUIDSetting("trackedMarkId", this); } /** copy constructor */ @@ -42,11 +38,10 @@ public class TrackedElementWithDeviceId extends AbstractGenericSerializableSetti @Override protected void addChildSettings() { - // We do not create the Setting instances here, because access to the RacingEventService would not be given. - // Doing this, Java/GWT Serialization isn't working anymore. Because the preferences are only serialized as JSON - // in the backend an transferred as DTO to the frontend, this isn't a problem. Due to usage of BoatClass and - // Competitor domain objects, it wouldn't be GWT compatible anyway. - // The usage of Java Serialization isn't planned by now, either. + deviceId = new StringSetting("deviceId", this); + trackedCompetitorId = new UUIDSetting("trackedCompetitorId", this); + trackedBoatId = new UUIDSetting("trackedBoatId", this); + trackedMarkId = new UUIDSetting("trackedMarkId", this); } public String getDeviceId() { From 1fe4faed9f3c5dc0a6ca4ec5d96421f1acaf7a8b Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Thu, 27 Jun 2019 15:08:00 +0200 Subject: [PATCH 49/69] Bug 4960: adjusted update POST method in TrackedEventsResource --- .../sailing/selenium/api/event/TrackedEventsApi.java | 8 +++----- .../gateway/jaxrs/api/TrackedEventsResource.java | 8 +++++--- .../webservices/api/v1/trackedeventsPostDoc.html | 12 ++++++------ 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java index ea032938cd5..285d1527eea 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java @@ -65,11 +65,9 @@ public class TrackedEventsApi { } public void setArchived(ApiContext ctx, String eventId, String leaderboardName, boolean archived) { - final HashMap queryParams = new HashMap<>(); - queryParams.put(KEY_EVENT_ID, eventId); - queryParams.put(KEY_LEADERBOARD_NAME, leaderboardName); - queryParams.put(KEY_QUERY_INCLUDE_ARCHIVED, Boolean.toString(archived)); - ctx.post(TRACKED_EVENTS_URL, queryParams); + final HashMap formParams = new HashMap<>(); + formParams.put(KEY_QUERY_INCLUDE_ARCHIVED, Boolean.toString(archived)); + ctx.post(TRACKED_EVENTS_URL + eventId + "/" + leaderboardName, new HashMap(), formParams); } public void deleteEventTrackings(ApiContext ctx, String eventId, String leaderboardName) { diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index bc722d41c17..0124ce69114 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -11,6 +11,7 @@ import java.util.function.Function; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; +import javax.ws.rs.FormParam; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; @@ -300,9 +301,10 @@ public class TrackedEventsResource extends AbstractSailingServerResource { } @POST - public Response updateTrackedEventsArchivedStatus(@QueryParam(KEY_EVENT_ID) String eventId, - @QueryParam(KEY_LEADERBOARD_NAME) String leaderboardName, - @QueryParam(KEY_QUERY_INCLUDE_ARCHIVED) String archived) { + @Path("{eventId}/{leaderboardName}") + public Response updateTrackedEventsArchivedStatus(@PathParam(KEY_EVENT_ID) String eventId, + @PathParam(KEY_LEADERBOARD_NAME) String leaderboardName, + @FormParam(KEY_QUERY_INCLUDE_ARCHIVED) String archived) { final boolean isArchived = Boolean.parseBoolean(archived); return applyOnEventByIdAndLeadboardName(eventId, leaderboardName, pref -> new TrackedEventPreference(pref, isArchived)); diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/trackedeventsPostDoc.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/trackedeventsPostDoc.html index bf9b0f574a2..e8f2522e2db 100644 --- a/java/com.sap.sailing.server.gateway/webservices/api/v1/trackedeventsPostDoc.html +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/trackedeventsPostDoc.html @@ -28,10 +28,10 @@ Mandatory parameters: - eventId: Identifier of the associated event
      - leaderboardName: Name of the associated leaderboard
      - isArchived: True or False depending on whether the event should be - set to archived or non-archived. + eventId (Path parameter): Identifier of the associated event
      + leaderboardName (Path parameter): Name of the associated leaderboard
      + isArchived (Form parameter): True or False depending on whether the + event should be set to archived or non-archived. @@ -45,8 +45,8 @@ Example: Request: - http://www.sapsailing.com/sailingserver/api/v1/trackedevents?eventId=71fe232b-19b8-455f-ac91-23a53a5c557a&leaderbaordName=TestRegattaLeaderboard
      - Status 202
      + http://www.sapsailing.com/sailingserver/api/v1/trackedevents/71fe232b-19b8-455f-ac91-23a53a5c557a/TestRegattaLeaderboard
      + form: isArchived=true
      Status 202
      From 27b77adbddc38e9cc2eada82e9a39cf4bd2f9009 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Thu, 27 Jun 2019 15:10:33 +0200 Subject: [PATCH 50/69] Bug 4960: fixed bug where empty element was sent if the event does not exist on this server --- .../jaxrs/api/TrackedEventsResource.java | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index 0124ce69114..c9db084bf9e 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -92,9 +92,9 @@ public class TrackedEventsResource extends AbstractSailingServerResource { final UUID eventId = pref.getEventId(); final Event event = getService().getEvent(eventId); + final JSONObject jsonEvent = new JSONObject(); if (event != null) { - // event actually exists -> parse relevant data - final JSONObject jsonEvent = new JSONObject(); + // event actually exists on this server -> parse relevant data if (getSecurityService().hasCurrentUserReadPermission(event)) { // user has read permission on event -> add additional event-specific data final OwnershipAnnotation ownership = getSecurityService() @@ -111,19 +111,21 @@ public class TrackedEventsResource extends AbstractSailingServerResource { .findImagesWithTag(MediaTagConstants.LOGO.getName()); if (!imageWithLogoTag.isEmpty()) { jsonEvent.put(KEY_EVENT_IMAGE_URL, imageWithLogoTag.get(0).getURL().toExternalForm()); + } else { + // user does not have read permissions for this event on this server -> only send back + // basic data } } - jsonEvent.put(KEY_EVENT_ID, pref.getEventId().toString()); - jsonEvent.put(KEY_EVENT_REGATTA_SECRET, pref.getRegattaSecret()); - jsonEvent.put(KEY_EVENT_BASE_URL, pref.getBaseUrl()); - jsonEvent.put(KEY_EVENT_IS_ARCHIVED, pref.getIsArchived()); - jsonEvent.put(KEY_LEADERBOARD_NAME, pref.getLeaderboardName()); - jsonEvent.put(KEY_EVENT_TRACKED_ELEMENTS, trackedElementsToJson(pref)); - result.add(jsonEvent); } else { - // TODO: - // check, if base url is equal to this server, if not, event might be on different server + // event does not exist on this server --> only send back basic data } + jsonEvent.put(KEY_EVENT_ID, pref.getEventId().toString()); + jsonEvent.put(KEY_EVENT_REGATTA_SECRET, pref.getRegattaSecret()); + jsonEvent.put(KEY_EVENT_BASE_URL, pref.getBaseUrl()); + jsonEvent.put(KEY_EVENT_IS_ARCHIVED, pref.getIsArchived()); + jsonEvent.put(KEY_LEADERBOARD_NAME, pref.getLeaderboardName()); + jsonEvent.put(KEY_EVENT_TRACKED_ELEMENTS, trackedElementsToJson(pref)); + result.add(jsonEvent); } } From ca018fec4e8776f8646c2b22e406351b97e83a3e Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 2 Jul 2019 13:45:46 +0200 Subject: [PATCH 51/69] Bug 4960: Adjusted TrackedEventsResource and associated tests to enable idempotency of PUT method --- .../selenium/api/event/TrackedEventsApi.java | 24 +++-- .../test/TrackedEventsResourceApiTest.java | 38 ++++--- .../jaxrs/api/TrackedEventsResource.java | 102 +++++++----------- 3 files changed, 73 insertions(+), 91 deletions(-) diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java index 285d1527eea..1483d46e4b5 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java @@ -4,12 +4,14 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Map; +import java.util.Set; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import com.sap.sailing.selenium.api.core.ApiContext; import com.sap.sailing.selenium.api.core.JsonWrapper; +import com.sap.sse.common.Util.Triple; public class TrackedEventsApi { @@ -42,21 +44,23 @@ public class TrackedEventsApi { } public void updateOrCreateTrackedEvent(ApiContext ctx, String eventId, String leaderboardName, String eventBaseUrl, - String deviceId, String competitorId, String boatId, String markId, String regattaSecret) { + String deviceId, Set> trackedIds, String regattaSecret) { final JSONObject json = new JSONObject(); json.put(KEY_EVENT_BASE_URL, eventBaseUrl); final JSONArray elements = new JSONArray(); - final JSONObject elem = new JSONObject(); - elem.put(KEY_TRACKED_ELEMENT_DEVICE_ID, deviceId); - if (competitorId != null) { - elem.put(KEY_TRACKED_ELEMENT_COMPETITOR_ID, competitorId); - } else if (boatId != null) { - elem.put(KEY_TRACKED_ELEMENT_BOAT_ID, boatId); - } else if (markId != null) { - elem.put(KEY_TRACKED_ELEMENT_MARK_ID, markId); + for (Triple trackedId : trackedIds) { + final JSONObject elem = new JSONObject(); + elem.put(KEY_TRACKED_ELEMENT_DEVICE_ID, deviceId); + if (trackedId.getA() != null) { + elem.put(KEY_TRACKED_ELEMENT_COMPETITOR_ID, trackedId.getA()); + } else if (trackedId.getB() != null) { + elem.put(KEY_TRACKED_ELEMENT_BOAT_ID, trackedId.getB()); + } else if (trackedId.getC() != null) { + elem.put(KEY_TRACKED_ELEMENT_MARK_ID, trackedId.getC()); + } + elements.add(elem); } - elements.add(elem); json.put(KEY_EVENT_REGATTA_SECRET, regattaSecret); json.put(KEY_EVENT_TRACKED_ELEMENTS, elements); diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java index 01720a38bdc..8fb509279a9 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java @@ -4,6 +4,9 @@ import static com.sap.sailing.selenium.api.core.ApiContext.SERVER_CONTEXT; import static com.sap.sailing.selenium.api.core.ApiContext.createAdminApiContext; import static com.sap.sailing.selenium.api.core.ApiContext.createApiContext; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; import java.util.UUID; import org.junit.Assert; @@ -21,6 +24,7 @@ import com.sap.sailing.selenium.api.event.TrackedEventsApi.TrackedEvent; import com.sap.sailing.selenium.api.event.TrackedEventsApi.TrackedEvents; import com.sap.sailing.selenium.test.AbstractSeleniumTest; import com.sap.sse.common.Util; +import com.sap.sse.common.Util.Triple; public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { @@ -64,12 +68,13 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { final String leaderboardName2 = evt2.getName(); final String regattaSecret2 = evt.getSecret(); + final Set> trackedIds = new HashSet<>(); + trackedIds.add(new Triple<>(competitorId, null, null)); + trackedIds.add(new Triple<>(null, boatId, null)); trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, - competitorId, null, null, regattaSecret); - trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, null, - boatId, null, regattaSecret); - trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, eventId2, leaderboardName2, eventBaseUrl, deviceId, null, - null, markId, regattaSecret2); + trackedIds, regattaSecret); + trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, eventId2, leaderboardName2, eventBaseUrl, deviceId, + new HashSet<>(Arrays.asList(new Triple<>(null, null, markId))), regattaSecret2); trackedEventsApi.setArchived(adminCtx, evt.getId(), leaderboardName, true); trackedEventsApi.setArchived(adminCtx, evt2.getId(), leaderboardName2, false); @@ -132,12 +137,13 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { final String leaderboardName2 = evt2.getName(); final String regattaSecret2 = evt2.getSecret(); + final Set> trackedIds = new HashSet<>(); + trackedIds.add(new Triple<>(competitorId, null, null)); + trackedIds.add(new Triple<>(null, boatId, null)); trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, - competitorId, null, null, regattaSecret); - trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, null, - boatId, null, regattaSecret); - trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, eventId2, leaderboardName2, eventBaseUrl, deviceId, null, - null, markId, regattaSecret2); + trackedIds, regattaSecret); + trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, eventId2, leaderboardName2, eventBaseUrl, deviceId, + new HashSet<>(Arrays.asList(new Triple<>(null, null, markId))), regattaSecret2); // check if created event is still there final TrackedEvents trackedEvents = trackedEventsApi.getTrackedEvents(adminCtx, true); @@ -193,12 +199,12 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { final String leaderboardName = evt.getName(); final String regattaSecret = evt.getSecret(); + final Set> trackedIds = new HashSet<>(); + trackedIds.add(new Triple<>(competitorId, null, null)); + trackedIds.add(new Triple<>(null, boatId, null)); + trackedIds.add(new Triple<>(null, null, markId)); trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, - competitorId, null, null, regattaSecret); - trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, null, - boatId, null, regattaSecret); - trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, null, - null, markId, regattaSecret); + trackedIds, regattaSecret); // check if created event is still there final TrackedEvents trackedEvents = trackedEventsApi.getTrackedEvents(adminCtx, true); @@ -261,7 +267,7 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { final String regattaSecret = evt.getSecret(); trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, - competitorId, boatId, markId, regattaSecret); + new HashSet<>(Arrays.asList(new Triple<>(competitorId, boatId, markId))), regattaSecret); // check if created event is still there final TrackedEvents trackedEvents = trackedEventsApi.getTrackedEvents(adminCtx, true); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index c9db084bf9e..ce8914b3045 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -1,13 +1,13 @@ package com.sap.sailing.server.gateway.jaxrs.api; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.UUID; import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; @@ -192,20 +192,21 @@ public class TrackedEventsResource extends AbstractSailingServerResource { // too few children responseBuilder = Response.status(Status.BAD_REQUEST) .entity("Invalid JSON body in request: Tracked element is missing."); - } else if (trackedElementsJson.size() > 1) { - // too many children - responseBuilder = Response.status(Status.BAD_REQUEST).entity( - "Invalid JSON body in request: Too many tracked elements: Only updating one tracked element per call is allowed."); } else { - // tracked json elements array has exactly one child - final JSONObject jsonTrackedElement = (JSONObject) trackedElementsJson.get(0); - if (jsonTrackedElement == null) { - responseBuilder = Response.status(Status.BAD_REQUEST) - .entity("Invalid JSON body in request: Tracked element is missing in array."); - } + // Copy tracked event preference objects to new list while removing the changed + // event/leaderboard node + final Collection prefsNew = // + StreamSupport.stream(prefs.getTrackedEvents().spliterator(), false) + .filter(pref -> !(pref.getEventId().equals(uuidEvent) + && pref.getLeaderboardName().equals(leaderboardName))) + .collect(Collectors.toList()); - else { + // Create new tracked elements for this event/leaderboard from JSON body + final Collection trackedElements = new ArrayList<>(); + + for (int i = 0; i < trackedElementsJson.size(); i++) { + final JSONObject jsonTrackedElement = (JSONObject) trackedElementsJson.get(i); // parse IDs final String deviceId = (String) jsonTrackedElement.get(KEY_TRACKED_ELEMENT_DEVICE_ID); @@ -215,68 +216,34 @@ public class TrackedEventsResource extends AbstractSailingServerResource { final String markIdStr = (String) jsonTrackedElement.get(KEY_TRACKED_ELEMENT_MARK_ID); // parse UUIDs of tracked element - final UUID competitorId; - final UUID boatId; - final UUID markId; - if (competitorIdStr != null && !competitorIdStr.isEmpty()) { - competitorId = parseUUID(competitorIdStr); - boatId = null; - markId = null; - } else if (boatIdStr != null && !boatIdStr.isEmpty()) { - competitorId = null; - boatId = parseUUID(boatIdStr); - markId = null; - } else if (markIdStr != null && !markIdStr.isEmpty()) { - boatId = null; - competitorId = null; - markId = parseUUID(markIdStr); - } else { - markId = boatId = competitorId = null; - } + final UUID competitorId = parseUUID(competitorIdStr); + final UUID boatId = parseUUID(boatIdStr); + final UUID markId = parseUUID(markIdStr); - if (boatId != null || markId != null || competitorId != null) { + if (boatId != null ^ markId != null ^ competitorId != null) { // create TrackedElementWithID holder final TrackedElementWithDeviceId newPrefElem = new TrackedElementWithDeviceId(deviceId, boatId, competitorId, markId); + trackedElements.add(newPrefElem); - final Collection prefsNew = new ArrayList<>(); - final Iterator it = prefs.getTrackedEvents().iterator(); - - // add newPrefElem to correct event or create a tracked event - boolean eventContained = false; - while (it.hasNext()) { - final TrackedEventPreference pref = it.next(); - if (pref.getEventId().equals(uuidEvent) - && pref.getLeaderboardName().equals(leaderboardName)) { - // tracked event found, add to event - prefsNew.add(new TrackedEventPreference(pref, newPrefElem)); - eventContained = true; - } else { - prefsNew.add(pref); - } - } - - if (!eventContained) { - // event was not found, create a new tracked event - final TrackedEventPreference newPreference = new TrackedEventPreference(uuidEvent, - leaderboardName, Arrays.asList(newPrefElem), baseUrl, isArchived, - regattaSecret); - prefsNew.add(newPreference); - } - - // update preferences - prefs.setTrackedEvents(prefsNew); - getSecurityService().setPreferenceObject(currentUser.getName(), - SailingPreferences.TRACKED_EVENTS_PREFERENCES, prefs); - responseBuilder = Response.status(Status.ACCEPTED); } else { // no boatId, competitorId or markId were specified responseBuilder = Response.status(Status.BAD_REQUEST) .entity("Invalid JSON body in request."); } + } + final TrackedEventPreference newPreference = new TrackedEventPreference(uuidEvent, + leaderboardName, trackedElements, baseUrl, isArchived, regattaSecret); + prefsNew.add(newPreference); + + prefs.setTrackedEvents(prefsNew); + + getSecurityService().setPreferenceObject(currentUser.getName(), + SailingPreferences.TRACKED_EVENTS_PREFERENCES, prefs); + responseBuilder = Response.status(Status.ACCEPTED); } } catch (IllegalArgumentException | ClassCastException e) { @@ -294,9 +261,14 @@ public class TrackedEventsResource extends AbstractSailingServerResource { private UUID parseUUID(String potentialUUID) { UUID uuid; - try { - uuid = UUID.fromString(potentialUUID); - } catch (IllegalArgumentException e) { + if (potentialUUID != null && !potentialUUID.isEmpty()) { + + try { + uuid = UUID.fromString(potentialUUID); + } catch (IllegalArgumentException e) { + uuid = null; + } + } else { uuid = null; } return uuid; From cc29c042ca5019fa7b11ce7939780be0eccbfffc Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Tue, 2 Jul 2019 13:47:06 +0200 Subject: [PATCH 52/69] Bug 4960: adjusted documentation according to last commit --- .../webservices/api/v1/trackedeventsPutDoc.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/trackedeventsPutDoc.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/trackedeventsPutDoc.html index 47ca142ee3e..0ebae75b94f 100644 --- a/java/com.sap.sailing.server.gateway/webservices/api/v1/trackedeventsPutDoc.html +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/trackedeventsPutDoc.html @@ -14,7 +14,7 @@

      URL: /api/v1/trackedevents/{eventId}/{leaderboardName}

      Description: -

      Create or update a tracked event for the current user.

      +

      Create or update a tracked event for the current user and set (overwrite) all tracked elements.


      From 59be22f8e3179dfc5a3635331323bf1257599cbf Mon Sep 17 00:00:00 2001 From: Robert Benedikt Date: Thu, 4 Jul 2019 12:53:47 +0200 Subject: [PATCH 53/69] Catch NumberFormatException to avoid app crashes --- .../app/ui/views/IntegerEditTextPreference.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/views/IntegerEditTextPreference.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/views/IntegerEditTextPreference.java index 33ca650fb8f..5984b00a015 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/views/IntegerEditTextPreference.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/views/IntegerEditTextPreference.java @@ -25,6 +25,10 @@ public class IntegerEditTextPreference extends EditTextPreference { @Override protected boolean persistString(String value) { - return persistInt(Integer.valueOf(value)); + try { + return persistInt(Integer.valueOf(value)); + } catch (NumberFormatException e) { + return false; + } } } From 70ccfe58f8693019008f8aa7abbf688091f93f36 Mon Sep 17 00:00:00 2001 From: Robert Benedikt Date: Thu, 4 Jul 2019 12:57:14 +0200 Subject: [PATCH 54/69] Simplify protest time settings and consider the custom input value --- .../res/values/preferences.xml | 3 --- .../racecommittee/app/AppPreferences.java | 21 ------------------- ...PreferencesRegattaConfigurationLoader.java | 9 +++----- .../app/ui/activities/LoginActivity.java | 1 - .../dialogs/ProtestTimeDialogFragment.java | 15 ++++--------- 5 files changed, 7 insertions(+), 42 deletions(-) diff --git a/mobile/com.sap.sailing.racecommittee.app/res/values/preferences.xml b/mobile/com.sap.sailing.racecommittee.app/res/values/preferences.xml index 4ca558792cb..0dc9932dd42 100755 --- a/mobile/com.sap.sailing.racecommittee.app/res/values/preferences.xml +++ b/mobile/com.sap.sailing.racecommittee.app/res/values/preferences.xml @@ -116,9 +116,6 @@ true protestTimeDuration 90 - protestTimeDurationCustom - protestTimeDurationCustomEditable - true allow_demo false diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/AppPreferences.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/AppPreferences.java index 88081708281..3c3c607a367 100755 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/AppPreferences.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/AppPreferences.java @@ -523,33 +523,12 @@ public class AppPreferences { context.getResources().getInteger(R.integer.preference_protest_time_duration_default)); } - public int getProtestTimeDurationInMinutesCustom() { - return helper.getInt(context.getString(R.string.preference_protest_time_duration_custom_key), -1); - } - - public boolean isDefaultProtestTimeCustomEditable() { - return helper.getBoolean(context.getString(R.string.preference_protest_time_duration_custom_editable_key), - context.getResources().getBoolean(R.bool.preference_protest_time_duration_custom_editable_default)); - } - public void setDefaultProtestTimeDurationInMinutes(int protestTimeInMinutes) { helper.getEditor() .putInt(context.getString(R.string.preference_protest_time_duration_key), protestTimeInMinutes) .commit(); } - public void setDefaultProtestTimeDurationInMinutesCustom(int protestTimeInMinutest) { - helper.getEditor() - .putInt(context.getString(R.string.preference_protest_time_duration_custom_key), protestTimeInMinutest) - .commit(); - } - - public void setDefaultProtestTimeDurationInMinutesCustomEditable(boolean editable) { - helper.getEditor() - .putBoolean(context.getString(R.string.preference_protest_time_duration_custom_editable_key), editable) - .commit(); - } - public void setAccessToken(String accessToken) { helper.getEditor().putString(context.getString(R.string.preference_access_token_key), accessToken).commit(); } diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/domain/configuration/impl/PreferencesRegattaConfigurationLoader.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/domain/configuration/impl/PreferencesRegattaConfigurationLoader.java index ee70bfe07f2..6761a04c23a 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/domain/configuration/impl/PreferencesRegattaConfigurationLoader.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/domain/configuration/impl/PreferencesRegattaConfigurationLoader.java @@ -1,8 +1,5 @@ package com.sap.sailing.racecommittee.app.domain.configuration.impl; -import java.util.ArrayList; -import java.util.HashSet; - import com.sap.sailing.android.shared.logging.ExLog; import com.sap.sailing.domain.base.configuration.ConfigurationLoader; import com.sap.sailing.domain.base.configuration.RacingProcedureConfiguration; @@ -23,6 +20,9 @@ import com.sap.sailing.domain.common.racelog.RacingProcedureType; import com.sap.sailing.racecommittee.app.AppPreferences; import com.sap.sse.common.Duration; +import java.util.ArrayList; +import java.util.HashSet; + public class PreferencesRegattaConfigurationLoader implements ConfigurationLoader { private static final String TAG = PreferencesRegattaConfigurationLoader.class.getSimpleName(); @@ -113,9 +113,6 @@ public class PreferencesRegattaConfigurationLoader implements ConfigurationLoade if (configuration.getDefaultProtestTimeDuration() != null) { preferences.setDefaultProtestTimeDurationInMinutes( (int) configuration.getDefaultProtestTimeDuration().asMinutes()); - preferences.setDefaultProtestTimeDurationInMinutesCustomEditable(false); - } else { - preferences.setDefaultProtestTimeDurationInMinutesCustomEditable(true); } if (configuration.getRRS26Configuration() != null) { diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/LoginActivity.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/LoginActivity.java index 29ffac51c1d..ecec4e0db61 100755 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/LoginActivity.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/LoginActivity.java @@ -401,7 +401,6 @@ public class LoginActivity extends BaseActivity implements EventSelectedListener public void onLoadFailed(Exception reason) { dismissProgressSpinner(); - preferences.setDefaultProtestTimeDurationInMinutesCustomEditable(true); if (reason instanceof FileNotFoundException) { Toast.makeText(getApplicationContext(), getString(R.string.loading_configuration_not_found), Toast.LENGTH_LONG).show(); diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/dialogs/ProtestTimeDialogFragment.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/dialogs/ProtestTimeDialogFragment.java index 0ed8e6ca2a7..606b9b19d86 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/dialogs/ProtestTimeDialogFragment.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/dialogs/ProtestTimeDialogFragment.java @@ -319,8 +319,7 @@ public class ProtestTimeDialogFragment extends AttachedDialogFragment implements TimePoint startTime = TimeUtils.getTime(mTimePicker); TimePoint now = MillisecondsTimePoint.now(); for (ManagedRace race : selectedRaces) { - Duration duration = Duration.ONE_MINUTE - .times(AppPreferences.on(getActivity()).getProtestTimeDurationInMinutes()); + Duration duration = Duration.ONE_MINUTE.times(mDuration); TimeRange protestTime = new TimeRangeImpl(startTime, startTime.plus(duration)); race.getState().setProtestTime(now, protestTime); } @@ -404,12 +403,6 @@ public class ProtestTimeDialogFragment extends AttachedDialogFragment implements private void updateProtestRange() { if (mDuration == null) { mDuration = mPreferences.getProtestTimeDurationInMinutes(); - if (mPreferences.isDefaultProtestTimeCustomEditable()) { - int custom = mPreferences.getProtestTimeDurationInMinutesCustom(); - if (custom >= 0) { - mDuration = custom; - } - } } if (mProtestDuration != null) { mProtestDuration.setText(getString(R.string.protest_duration, mDuration)); @@ -468,9 +461,9 @@ public class ProtestTimeDialogFragment extends AttachedDialogFragment implements builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - mDuration = Integer.parseInt(duration.getText().toString()); - if (mPreferences.isDefaultProtestTimeCustomEditable()) { - mPreferences.setDefaultProtestTimeDurationInMinutesCustom(mDuration); + try { + mDuration = Integer.parseInt(duration.getText().toString()); + } catch (NumberFormatException ignored) { } updateProtestRange(); } From 28be354bce5de0f63a3de9187157042e4185464f Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Fri, 5 Jul 2019 12:39:39 +0200 Subject: [PATCH 55/69] Bug 5057: Added the possibility to add an existing competitor to a regatta using the secret --- .../gateway/jaxrs/api/RegattasResource.java | 8 ++- .../webservices/api/v1/index.html | 2 +- .../api/v1/regattasCompetitorAdd.html | 50 +++++++++++++++++++ 3 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 java/com.sap.sailing.server.gateway/webservices/api/v1/regattasCompetitorAdd.html diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java index 9c4d4653eb5..37b72572b01 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java @@ -349,13 +349,17 @@ public class RegattasResource extends AbstractSailingServerResource { @Produces("application/json;charset=UTF-8") @Path("{regattaname}/competitors/{competitorid}/add") public Response addCompetitor(@PathParam("regattaname") String regattaName, - @PathParam("competitorid") String competitorIdAsString) { + @PathParam("competitorid") String competitorIdAsString, + @QueryParam("secret") String registrationLinkSecret) { Response response; Regatta regatta = findRegattaByName(regattaName); if (regatta == null) { response = getBadRegattaErrorResponse(regattaName); } else { - getSecurityService().checkCurrentUserUpdatePermission(regatta); + boolean skipPermissionCheck = getService().skipChecksDueToCorrectSecret(regattaName, registrationLinkSecret); + if (!skipPermissionCheck) { + getSecurityService().checkCurrentUserUpdatePermission(regatta); + } Serializable competitorId; try { competitorId = UUID.fromString(competitorIdAsString); diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html index b36bfcfac64..e1ce1d05bc3 100644 --- a/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html @@ -154,7 +154,7 @@ name to make sure you get to the event you're interested in. - + diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/regattasCompetitorAdd.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/regattasCompetitorAdd.html new file mode 100644 index 00000000000..1d833f24430 --- /dev/null +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/regattasCompetitorAdd.html @@ -0,0 +1,50 @@ + + + + + + + + SAP Sailing Analytics Webservices API Version 1.0 + + +

      SAP Sailing Analytics Webservices API Version 1.0

      +

      URL: /api/v1/regattas/{regattaname}/competitors/{competitorId}/add

      + +Description: +

      Registers an existing competitor with the regatta.
      +This provides functionality

    • for the regatta owner (or any user with update permission on the regatta) to add existing +competitors to the regatta
    • and for any user to register himself to an regatta that is explicitly open for self-registrations.
      +All slashes contained within the {regattaname} parameter must be replaced by "__" (double underscore).

      +
      +
    • Creates a competitor and adds it to the regatta
      /api/v1/regattas/{regattaname}/competitors/{competitorId}/add/api/v1/regattas/{regattaname}/competitors/{competitorId}/add Registers a competitor with a regatta (POST)
      + + + + + + + + + + + + + + + + + + + + +
      Webservice Type:POST
      Output format:None
      Mandatory parameters: +
      regattaname the name of the regatta to register a competitor for
      +
      competitorid the UUID of the competitor to register
      +
      Additional mandatory parameters for user self-registrations on open regattas: +
      secret secret string required for self registration validation purpose
      +
      Request method:POST
      +
      +Back to Web Service Overview + + From b6e3ab3079dde11fa79ebdb39ac188d519cf2258 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Fri, 5 Jul 2019 12:40:26 +0200 Subject: [PATCH 56/69] Bug 5057: First (non-working) version of an API test for adding an existing competitor --- .../selenium/api/regatta/RegattaApi.java | 11 +++++++- .../selenium/api/test/RegattaApiTest.java | 27 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/regatta/RegattaApi.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/regatta/RegattaApi.java index 679a0b7bfb8..13fc436cdba 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/regatta/RegattaApi.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/regatta/RegattaApi.java @@ -14,7 +14,9 @@ public class RegattaApi { private static final String REGATTAS = "/api/v1/regattas"; private static final String LIST_REGATTA_RACES = "/races"; - private static final String COMPETITOR_CREATE_AND_ADD_WITH_BOAT = "/competitors/createandadd"; + private static final String COMPETITORS = "/competitors"; + private static final String COMPETITOR_CREATE_AND_ADD_WITH_BOAT = COMPETITORS + "/createandadd"; + private static final String ADD = "/add"; private static final String ADD_RACE_COLUMN_URL = "/addracecolumns"; public Regatta getRegatta(ApiContext ctx, String regattaName) { @@ -76,5 +78,12 @@ public class RegattaApi { } return result; } + + public void addCompetitor(ApiContext ctx, String regattaName, UUID competitorId, Optional secret) { + final String url = REGATTAS + "/" + regattaName + COMPETITORS + "/" + competitorId + ADD; + final Map queryParams = new TreeMap<>(); + queryParams.put("secret", secret.orElse(null)); + ctx.post(url, queryParams); + } } diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/RegattaApiTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/RegattaApiTest.java index e6e42f24809..7b50ef93bcf 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/RegattaApiTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/RegattaApiTest.java @@ -3,18 +3,24 @@ package com.sap.sailing.selenium.api.test; import static com.sap.sailing.domain.common.CompetitorRegistrationType.CLOSED; import static com.sap.sailing.selenium.api.core.ApiContext.SERVER_CONTEXT; import static com.sap.sailing.selenium.api.core.ApiContext.createAdminApiContext; +import static com.sap.sailing.selenium.api.core.ApiContext.createApiContext; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import java.util.Optional; + import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.junit.Before; import org.junit.Test; +import com.sap.sailing.domain.common.CompetitorRegistrationType; import com.sap.sailing.selenium.api.core.ApiContext; import com.sap.sailing.selenium.api.event.EventApi; +import com.sap.sailing.selenium.api.event.EventApi.Event; import com.sap.sailing.selenium.api.event.LeaderboardApi; +import com.sap.sailing.selenium.api.event.SecurityApi; import com.sap.sailing.selenium.api.regatta.Competitor; import com.sap.sailing.selenium.api.regatta.RaceColumn; import com.sap.sailing.selenium.api.regatta.Regatta; @@ -25,6 +31,7 @@ import com.sap.sailing.selenium.test.AbstractSeleniumTest; public class RegattaApiTest extends AbstractSeleniumTest { private static String EVENT_NAME = " loggingsession"; + private static String OTHER_EVENT_NAME = " loggingsession"; private static String BOAT_CLASS = "75QMNATIONALEKREUZER"; private final EventApi eventApi = new EventApi(); @@ -110,4 +117,24 @@ public class RegattaApiTest extends AbstractSeleniumTest { // assertEquals("read: racecolumn.seriesname is different", "Default", result[4].getSeriesName()); // assertEquals("read: racecolumn.racename is different", "T5", result[4].getRaceName()); } + + @Test + public void testRegisterExistingCompetitorWithSecret() { + SecurityApi securityApi = new SecurityApi(); + final ApiContext adminSecurityCtx = createAdminApiContext(getContextRoot(), SERVER_CONTEXT); + securityApi.createUser(adminSecurityCtx, "donald", "Donald Duck", null, "daisy0815"); + final ApiContext userWithCompetitorCtx = createApiContext(getContextRoot(), SERVER_CONTEXT, "donald", "daisy0815"); + securityApi.createUser(adminSecurityCtx, "dagobert", "Dagobert Duck", null, "daisy1337"); + final ApiContext userOwningEventCtx = createApiContext(getContextRoot(), SERVER_CONTEXT, "dagobert", "daisy1337"); + + // TODO we currently can't just create a competitor using the API. This is only possible by using a temporary Event/Regatta. + eventApi.createEvent(userWithCompetitorCtx, EVENT_NAME, BOAT_CLASS, CLOSED, "default"); + Competitor competitor = regattaApi.createAndAddCompetitor(userWithCompetitorCtx, EVENT_NAME, BOAT_CLASS, null, "donald", "USA"); + + // This is the event to register the existing competitor for + Event eventToRegisterExistingCompetitor = eventApi.createEvent(userWithCompetitorCtx, OTHER_EVENT_NAME, BOAT_CLASS, CompetitorRegistrationType.OPEN_UNMODERATED, "default"); + regattaApi.addCompetitor(userWithCompetitorCtx, OTHER_EVENT_NAME, competitor.getId(), Optional.of(eventToRegisterExistingCompetitor.getSecret())); + Regatta regatta = regattaApi.getRegatta(userOwningEventCtx, OTHER_EVENT_NAME); + System.out.println(regatta.getJson()); + } } From 0d5ca6aaaa694146b6d6c6c0b72330664cedcffc Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Fri, 5 Jul 2019 16:24:26 +0200 Subject: [PATCH 57/69] Bug 5057: Fixed API test for adding an existing competitor to an open regatta --- .../sailing/selenium/api/test/RegattaApiTest.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/RegattaApiTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/RegattaApiTest.java index 7b50ef93bcf..61ff5e69f38 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/RegattaApiTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/RegattaApiTest.java @@ -4,6 +4,7 @@ import static com.sap.sailing.domain.common.CompetitorRegistrationType.CLOSED; import static com.sap.sailing.selenium.api.core.ApiContext.SERVER_CONTEXT; import static com.sap.sailing.selenium.api.core.ApiContext.createAdminApiContext; import static com.sap.sailing.selenium.api.core.ApiContext.createApiContext; +import static com.sap.sailing.selenium.pages.adminconsole.AdminConsolePage.goToPage; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; @@ -26,6 +27,7 @@ import com.sap.sailing.selenium.api.regatta.RaceColumn; import com.sap.sailing.selenium.api.regatta.Regatta; import com.sap.sailing.selenium.api.regatta.RegattaApi; import com.sap.sailing.selenium.api.regatta.RegattaRaces; +import com.sap.sailing.selenium.pages.adminconsole.AdminConsolePage; import com.sap.sailing.selenium.test.AbstractSeleniumTest; public class RegattaApiTest extends AbstractSeleniumTest { @@ -41,6 +43,7 @@ public class RegattaApiTest extends AbstractSeleniumTest { @Before public void setUp() { clearState(getContextRoot()); + super.setUp(); } @Test @@ -120,8 +123,11 @@ public class RegattaApiTest extends AbstractSeleniumTest { @Test public void testRegisterExistingCompetitorWithSecret() { + final AdminConsolePage adminConsole = goToPage(getWebDriver(), getContextRoot()); + adminConsole.goToLocalServerPanel().setSelfServiceServer(true); + SecurityApi securityApi = new SecurityApi(); - final ApiContext adminSecurityCtx = createAdminApiContext(getContextRoot(), SERVER_CONTEXT); + final ApiContext adminSecurityCtx = createAdminApiContext(getContextRoot(), ApiContext.SECURITY_CONTEXT); securityApi.createUser(adminSecurityCtx, "donald", "Donald Duck", null, "daisy0815"); final ApiContext userWithCompetitorCtx = createApiContext(getContextRoot(), SERVER_CONTEXT, "donald", "daisy0815"); securityApi.createUser(adminSecurityCtx, "dagobert", "Dagobert Duck", null, "daisy1337"); @@ -132,9 +138,9 @@ public class RegattaApiTest extends AbstractSeleniumTest { Competitor competitor = regattaApi.createAndAddCompetitor(userWithCompetitorCtx, EVENT_NAME, BOAT_CLASS, null, "donald", "USA"); // This is the event to register the existing competitor for - Event eventToRegisterExistingCompetitor = eventApi.createEvent(userWithCompetitorCtx, OTHER_EVENT_NAME, BOAT_CLASS, CompetitorRegistrationType.OPEN_UNMODERATED, "default"); + Event eventToRegisterExistingCompetitor = eventApi.createEvent(userOwningEventCtx, OTHER_EVENT_NAME, BOAT_CLASS, CompetitorRegistrationType.OPEN_UNMODERATED, "default"); regattaApi.addCompetitor(userWithCompetitorCtx, OTHER_EVENT_NAME, competitor.getId(), Optional.of(eventToRegisterExistingCompetitor.getSecret())); - Regatta regatta = regattaApi.getRegatta(userOwningEventCtx, OTHER_EVENT_NAME); - System.out.println(regatta.getJson()); + + // TODO check if the competitor is added to the regatta } } From 17a2c1bde7ab079f4ebf0efbf7d80f31d41bc961 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Mon, 8 Jul 2019 15:33:42 +0200 Subject: [PATCH 58/69] Bug 5057: Implemented additional verification in API test --- .../com/sap/sailing/selenium/api/test/RegattaApiTest.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/RegattaApiTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/RegattaApiTest.java index a6f2453e8b9..a2c625c0121 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/RegattaApiTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/RegattaApiTest.java @@ -167,6 +167,9 @@ public class RegattaApiTest extends AbstractSeleniumTest { Event eventToRegisterExistingCompetitor = eventApi.createEvent(userOwningEventCtx, OTHER_EVENT_NAME, BOAT_CLASS, CompetitorRegistrationType.OPEN_UNMODERATED, "default"); regattaApi.addCompetitor(userWithCompetitorCtx, OTHER_EVENT_NAME, competitor.getId(), Optional.of(eventToRegisterExistingCompetitor.getSecret())); - // TODO check if the competitor is added to the regatta + Competitor[] competitors = regattaApi.getCompetitors(userOwningEventCtx, OTHER_EVENT_NAME); + + assertEquals(1, competitors.length); + assertEquals(competitor.getId(), competitors[0].getId()); } } From 470832af7a8f93b5660f47dd4cf0f7e0d4712f8b Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Mon, 8 Jul 2019 15:53:23 +0200 Subject: [PATCH 59/69] Bug 5057: Started with implementation of another selenium test case with a bad regatta secret --- .../selenium/api/test/RegattaApiTest.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/RegattaApiTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/RegattaApiTest.java index a6f2453e8b9..70a0a0d0594 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/RegattaApiTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/RegattaApiTest.java @@ -15,6 +15,7 @@ import java.util.Optional; import org.json.simple.JSONArray; import org.json.simple.JSONObject; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -169,4 +170,37 @@ public class RegattaApiTest extends AbstractSeleniumTest { // TODO check if the competitor is added to the regatta } + + @Test + public void testRegisterExistingCompetitorWithBadSecret() { + final AdminConsolePage adminConsole = goToPage(getWebDriver(), getContextRoot()); + adminConsole.goToLocalServerPanel().setSelfServiceServer(true); + + SecurityApi securityApi = new SecurityApi(); + final ApiContext adminSecurityCtx = createAdminApiContext(getContextRoot(), ApiContext.SECURITY_CONTEXT); + securityApi.createUser(adminSecurityCtx, "donald", "Donald Duck", null, "daisy0815"); + final ApiContext userWithCompetitorCtx = createApiContext(getContextRoot(), SERVER_CONTEXT, "donald", + "daisy0815"); + securityApi.createUser(adminSecurityCtx, "dagobert", "Dagobert Duck", null, "daisy1337"); + final ApiContext userOwningEventCtx = createApiContext(getContextRoot(), SERVER_CONTEXT, "dagobert", + "daisy1337"); + + // TODO we currently can't just create a competitor using the API. This is only possible by using a temporary + // Event/Regatta. + eventApi.createEvent(userWithCompetitorCtx, EVENT_NAME, BOAT_CLASS, CLOSED, "default"); + Competitor competitor = regattaApi.createAndAddCompetitor(userWithCompetitorCtx, EVENT_NAME, BOAT_CLASS, null, + "donald", "USA"); + + // This is the event to register the existing competitor for + Event eventToRegisterExistingCompetitor = eventApi.createEvent(userOwningEventCtx, OTHER_EVENT_NAME, BOAT_CLASS, + CompetitorRegistrationType.OPEN_UNMODERATED, "default"); + try { + regattaApi.addCompetitor(userWithCompetitorCtx, OTHER_EVENT_NAME, competitor.getId(), + Optional.of(eventToRegisterExistingCompetitor.getSecret() + "bad")); + Assert.fail("Expected error because of bad secret."); + } catch (RuntimeException e) { + Assert.assertTrue("Exepcted HTTP 401 - Unauthorized", e.getMessage().contains("rc=401")); + } + // TODO check if the competitor is added to the regatta + } } From 1c604cb258c8f2bb83ac9a2c97a7665eceed9c45 Mon Sep 17 00:00:00 2001 From: Robert Benedikt Date: Tue, 9 Jul 2019 15:37:01 +0200 Subject: [PATCH 60/69] Add release notes regarding the protest duration --- .../places/whatsnew/resources/RaceCommitteeAppNotes.html | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/whatsnew/resources/RaceCommitteeAppNotes.html b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/whatsnew/resources/RaceCommitteeAppNotes.html index 54054e529a0..cdda13a078a 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/whatsnew/resources/RaceCommitteeAppNotes.html +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/whatsnew/resources/RaceCommitteeAppNotes.html @@ -4,6 +4,14 @@

      What's New - SAP Sailing Race Manager

      +
      July 2019
      +
        +
      • The app no longer remembers the last entered duration when setting a protest time. + The protest duration can now be configured correctly in the app settings. + Please consider that a protest duration in the specific regatta configuration is preferred to + the protest duration in the default regatta configuration.
      • +
      +
      May 2019
      • The Course editor now works correctly when managing more than one regatta. From c8ca86156e0f396d4284ba23f1624df056d2122d Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Wed, 10 Jul 2019 18:27:04 +0200 Subject: [PATCH 61/69] Bug 5057: fixed JUnit tests for RegattaApi when using regatta secret during competitor registration --- .../selenium/api/test/RegattaApiTest.java | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/RegattaApiTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/RegattaApiTest.java index 74e5e591f59..ba2bfa470db 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/RegattaApiTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/RegattaApiTest.java @@ -12,6 +12,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.util.Optional; +import java.util.UUID; import org.json.simple.JSONArray; import org.json.simple.JSONObject; @@ -25,6 +26,8 @@ import com.sap.sailing.selenium.api.event.EventApi; import com.sap.sailing.selenium.api.event.EventApi.Event; import com.sap.sailing.selenium.api.event.LeaderboardApi; import com.sap.sailing.selenium.api.event.SecurityApi; +import com.sap.sailing.selenium.api.event.UserGroupApi; +import com.sap.sailing.selenium.api.event.UserGroupApi.UserGroup; import com.sap.sailing.selenium.api.regatta.Competitor; import com.sap.sailing.selenium.api.regatta.RaceColumn; import com.sap.sailing.selenium.api.regatta.Regatta; @@ -42,6 +45,7 @@ public class RegattaApiTest extends AbstractSeleniumTest { private final EventApi eventApi = new EventApi(); private final RegattaApi regattaApi = new RegattaApi(); private final LeaderboardApi leaderboardApi = new LeaderboardApi(); + private final UserGroupApi usergroupApi = new UserGroupApi(); @Before public void setUp() { @@ -157,6 +161,8 @@ public class RegattaApiTest extends AbstractSeleniumTest { final ApiContext adminSecurityCtx = createAdminApiContext(getContextRoot(), ApiContext.SECURITY_CONTEXT); securityApi.createUser(adminSecurityCtx, "donald", "Donald Duck", null, "daisy0815"); final ApiContext userWithCompetitorCtx = createApiContext(getContextRoot(), SERVER_CONTEXT, "donald", "daisy0815"); + final ApiContext userWithCompetitorAndSecurityCtx = createApiContext(getContextRoot(), + ApiContext.SECURITY_CONTEXT, "donald", "daisy0815"); securityApi.createUser(adminSecurityCtx, "dagobert", "Dagobert Duck", null, "daisy1337"); final ApiContext userOwningEventCtx = createApiContext(getContextRoot(), SERVER_CONTEXT, "dagobert", "daisy1337"); @@ -164,6 +170,11 @@ public class RegattaApiTest extends AbstractSeleniumTest { eventApi.createEvent(userWithCompetitorCtx, EVENT_NAME, BOAT_CLASS, CLOSED, "default"); Competitor competitor = regattaApi.createAndAddCompetitor(userWithCompetitorCtx, EVENT_NAME, BOAT_CLASS, null, "donald", "USA"); + // ensure the reader can actually see the competitor + UserGroup group = usergroupApi.getUserGroupByName(userWithCompetitorAndSecurityCtx, "donald-tenant"); + usergroupApi.addRoleToGroup(userWithCompetitorAndSecurityCtx, group.getGroupId(), + UUID.fromString(/* sailing viewer role id */"c42948df-517b-45cb-9fa9-d1e79f18e115"), true); + // This is the event to register the existing competitor for Event eventToRegisterExistingCompetitor = eventApi.createEvent(userOwningEventCtx, OTHER_EVENT_NAME, BOAT_CLASS, CompetitorRegistrationType.OPEN_UNMODERATED, "default"); regattaApi.addCompetitor(userWithCompetitorCtx, OTHER_EVENT_NAME, competitor.getId(), Optional.of(eventToRegisterExistingCompetitor.getSecret())); @@ -188,12 +199,20 @@ public class RegattaApiTest extends AbstractSeleniumTest { final ApiContext userOwningEventCtx = createApiContext(getContextRoot(), SERVER_CONTEXT, "dagobert", "daisy1337"); + final ApiContext userWithCompetitorAndSecurityCtx = createApiContext(getContextRoot(), + ApiContext.SECURITY_CONTEXT, "donald", "daisy0815"); + // TODO we currently can't just create a competitor using the API. This is only possible by using a temporary // Event/Regatta. eventApi.createEvent(userWithCompetitorCtx, EVENT_NAME, BOAT_CLASS, CLOSED, "default"); Competitor competitor = regattaApi.createAndAddCompetitor(userWithCompetitorCtx, EVENT_NAME, BOAT_CLASS, null, "donald", "USA"); + // ensure the reader can actually see the competitor + UserGroup group = usergroupApi.getUserGroupByName(userWithCompetitorAndSecurityCtx, "donald-tenant"); + usergroupApi.addRoleToGroup(userWithCompetitorAndSecurityCtx, group.getGroupId(), + UUID.fromString(/* sailing viewer role id */"c42948df-517b-45cb-9fa9-d1e79f18e115"), true); + // This is the event to register the existing competitor for Event eventToRegisterExistingCompetitor = eventApi.createEvent(userOwningEventCtx, OTHER_EVENT_NAME, BOAT_CLASS, CompetitorRegistrationType.OPEN_UNMODERATED, "default"); @@ -204,6 +223,9 @@ public class RegattaApiTest extends AbstractSeleniumTest { } catch (RuntimeException e) { Assert.assertTrue("Exepcted HTTP 401 - Unauthorized", e.getMessage().contains("rc=401")); } - // TODO check if the competitor is added to the regatta + + Competitor[] competitors = regattaApi.getCompetitors(userOwningEventCtx, OTHER_EVENT_NAME); + + assertEquals(0, competitors.length); } } From 9583ebc917ef21f32cf0721e2e033304e010f412 Mon Sep 17 00:00:00 2001 From: "service.tip.git" Date: Thu, 11 Jul 2019 15:22:52 +0000 Subject: [PATCH 62/69] [INTERNAL] Translation delivery: commit by LX Lab Change-Id: I1442cbbc2a1260de93d7b4959d2603cc01d0a80e --- .../gwt/ui/client/StringMessages_es.properties | 10 +++++++++- .../gwt/ui/client/StringMessages_fr.properties | 10 +++++++++- .../gwt/ui/client/StringMessages_it.properties | 18 +++++++++++++----- .../gwt/ui/client/StringMessages_ja.properties | 10 +++++++++- .../gwt/ui/client/StringMessages_pt.properties | 16 ++++++++++++---- .../gwt/ui/client/StringMessages_ru.properties | 10 +++++++++- .../gwt/ui/client/StringMessages_zh.properties | 14 +++++++++++--- 7 files changed, 72 insertions(+), 16 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_es.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_es.properties index 7747a105404..88c5081e6c2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_es.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_es.properties @@ -948,6 +948,7 @@ raceTimeUpwindTooltip=Tiempo total de ceñida recorrido en esta carrera noCustomGrouperScriptTextError=El script de grupo está vacío noGrouperSelectedError=No se ha seleccionado ningún tipo de agrupador dataMining=Minería de datos +changeOrientation=Modificar orientación hideToolbar=Ocultar barra de herramientas showSeriesLeaderboards=Mostrar tablas de clasificación de las series showOverallLeaderboard=Mostrar tabla de clasificación general @@ -1051,8 +1052,10 @@ resultFromIgtimiWindImport=Se ha importado el número siguiente de correcciones timeToStart={0} hasta la salida timeSinceStart={0} desde la salida distanceToLine=Distancia hasta la línea de salida -TWATooltip=Ángulo entre la dirección de los competidores y el viento +TWATooltip=El ángulo entre el rumbo de los competidores sobre el fondo y el viento, muestra valores negativos que implican viento de babor, valores positivos que implican viento de estribor. +absoluteTWATooltip=El ángulo positivo entre el rumbo de los competidores sobre el fondo y el viento, sin signo +/- TWA=Ángulo real del viento +absoluteTWA=Ángulo real absoluto del viento showBoatClassChartsLabel=También puede visualizar el diagrama global para las clases de embarcación disponibles. showDiagram=Mostrar diagrama rerunQueryAfterRefreshTooltip=Vuelve a ejecutar la consulta después de que se hayan refrescado las tablas. @@ -1927,6 +1930,7 @@ finishingTime=Hora de llegada finishTimeString=Hora de fin setFinishingAndFinishTime=Fijar hora de llegada y de fin finishTimeMustBeAtOrAfterFinishingTime=Hora de fin debe ser a la hora de llegada o posterior +youHaveToEnterAFinishingTimeIfYouEnterAFinishedTime=Debe indicar la hora de llegada si indica la hora de fin boatNameMustNotBeEmpty=Proporcione un nombre de embarcación que no esté en blanco errorUpdatingExpeditionDeviceConfiguration=Error al actualizar la configuración del dispositivo con la expedición "{0}": {1} doYouReallyWantToRemoveExpeditionDeviceConfiguration=¿Desea realmente eliminar la configuración del dispositivo con la expedición "{0}"? @@ -2255,3 +2259,7 @@ editSwissTimingConnections=Tratar conexión SwissTiming filterSwissTimingConnections=Filtrar conexiones SwissTiming addSwissTimingConnection=Añadir conexión SwissTiming updateURL=Actualizar URL +startProcedure=Iniciar procedimiento +startMode=Iniciar modo +gateOpeningTime=Horario de apertura de puerta +protestTimeInMinutes=Tiempo para protestar en minutos diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_fr.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_fr.properties index 297a661a664..d8113a3ef33 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_fr.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_fr.properties @@ -948,6 +948,7 @@ raceTimeUpwindTooltip=Durée totale de navigation dans le lit du vent dans cette noCustomGrouperScriptTextError=Script de regroupement vide noGrouperSelectedError=Aucun type de regroupement sélectionné dataMining=Exploration de données +changeOrientation=Modifier orientation hideToolbar=Masquer barre d''outils showSeriesLeaderboards=Afficher palmarès de la série showOverallLeaderboard=Afficher palmarès général @@ -1051,8 +1052,10 @@ resultFromIgtimiWindImport=Le nombre suivant de points vent ont été importés timeToStart={0} jusqu''au départ timeSinceStart={0} depuis le départ distanceToLine=Distance jusqu''à la ligne de départ -TWATooltip=L''angle entre la direction du concurrent et le vent. +TWATooltip=L''angle entre la route fond des concurrents et le vent, accompagné d''un signe : les valeurs négatives indiquent que le vent vient de bâbord, les valeurs positives indiquent que le vent vient de tribord. +absoluteTWATooltip=L''angle positif entre la route fond des concurrents et le vent, sans signe +/-. TWA=Angle du vent réel +absoluteTWA=Angle du vent réel absolu showBoatClassChartsLabel=Vous pouvez également afficher le diagramme global pour les catégories de bateau disponibles. showDiagram=Afficher diagramme rerunQueryAfterRefreshTooltip=Réexécute la requête après l''actualisation des tables. @@ -1927,6 +1930,7 @@ finishingTime=Heure d''arrivée du premier finishTimeString=Heure de fermeture de la ligne d''arrivée setFinishingAndFinishTime=Définir heure d''arrivée du premier et de fermeture de la ligne d''arrivée finishTimeMustBeAtOrAfterFinishingTime=L''heure de fermeture de la ligne d''arrivée doit être égale ou ultérieure à l''heure d''arrivée du premier. +youHaveToEnterAFinishingTimeIfYouEnterAFinishedTime=Vous devez saisir une heure d''arrivée du premier si vous saisissez une heure de fermeture de la ligne d''arrivée. boatNameMustNotBeEmpty=Veuillez indiquer un nom de bateau. errorUpdatingExpeditionDeviceConfiguration=Erreur lors de la mise à jour de la configuration du terminal Expedition "{0}" : {1} doYouReallyWantToRemoveExpeditionDeviceConfiguration=Voulez-vous vraiment supprimer la configuration du terminal Expedition "{0}" ? @@ -2255,3 +2259,7 @@ editSwissTimingConnections=Modifier connexion SwissTiming filterSwissTimingConnections=Filtrer connexions SwissTiming addSwissTimingConnection=Ajouter connexion SwissTiming updateURL=Mettre à jour URL +startProcedure=Procédure de départ +startMode=Mode de départ +gateOpeningTime=Heure d''ouverture de la porte +protestTimeInMinutes=Durée de réclamation en minutes diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_it.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_it.properties index d8f2c943a40..6bb5df9ba72 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_it.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_it.properties @@ -339,7 +339,7 @@ notAvailable=Non disponibile noGroupSelected=Nessun gruppo selezionato combinedWindSourceTypeName=Combinato legMiddleWindSourceTypeName=Metà della tratta -courseBasedWindSourceTypeName=Progettazione rotta +courseBasedWindSourceTypeName=Progettazione della rotta trackBasedEstimationWindSourceTypeName=Stima windSensorWindSourceTypeName=Misurato webWindSourceTypeName=Manuale @@ -948,6 +948,7 @@ raceTimeUpwindTooltip=Tempo totale di navigazione di bolina in questa gara noCustomGrouperScriptTextError=Script membro vuoto noGrouperSelectedError=Nessun tipo di membro selezionato dataMining=Estrazione dati +changeOrientation=Modifica orientamento hideToolbar=Nascondi barra degli strumenti showSeriesLeaderboards=Mostra classifiche serie showOverallLeaderboard=Mostra classifica generale @@ -1051,8 +1052,10 @@ resultFromIgtimiWindImport=Per le gare elencate è stato importato il seguente n timeToStart={0} all’inizio timeSinceStart={0} dall’inizio distanceToLine=Distanza fino alla linea di partenza -TWATooltip=L’angolo tra la direzione dei concorrenti e il vento +TWATooltip=L’angolo tra la rotta effettiva al fondo dei concorrenti e il vento tracciato, dove i valori negativi indicano il vento da sinistra e quelli positivi il vento da destra +absoluteTWATooltip=L''angolo positivo tra la rotta effettiva al fondo dei concorrenti e il vento, senza segno positivo o negativo TWA=Angolo del vento reale +absoluteTWA=Angolo assoluto del vento reale showBoatClassChartsLabel=È anche possibile visualizzare il diagramma complessivo delle classi di barca disponibili. showDiagram=Mostra diagramma rerunQueryAfterRefreshTooltip=Riesegue la query dopo che le tabelle sono state aggiornate. @@ -1927,6 +1930,7 @@ finishingTime=Ora conclusione finishTimeString=Ora di fine setFinishingAndFinishTime=Imposta ora conclusione e ora di fine finishTimeMustBeAtOrAfterFinishingTime=L’ora di fine deve essere uguale o successiva all’ora di conclusione +youHaveToEnterAFinishingTimeIfYouEnterAFinishedTime=Se si inserisce un''ora di fine occorre indicare un''ora di conclusione boatNameMustNotBeEmpty=Fornisci un nome barca non vuoto errorUpdatingExpeditionDeviceConfiguration=Errore nell’aggiornamento della configurazione del dispositivo Expedition "{0}": {1} doYouReallyWantToRemoveExpeditionDeviceConfiguration=Confermare l''eliminazione della configurazione del dispositivo Expedition "{0}"? @@ -2001,9 +2005,9 @@ raceNameIsRequired=Deve essere indicato un nome per la gara suddivisa. raceNameIsAlreadyUsed=Il nome indicato è già in uso errorWhilePreparingToSliceARace=Errore nella preparazione della suddivisione gara errorWhileSlicingARace=Errore nella suddivisione della gara -windFinderWindSourceTypeName= +windFinderWindSourceTypeName=Windfinder windFinderWindSourceTypeTooltip=Vento misurato da uno o più punti di www.windfinder.com -windFinder= +windFinder=Windfinder enterTagsForTheVideo=Inserisci i tag per il video enterIdOfWindFinderReviewedSpotCollection=Inserisci l''ID di una collezione di punti WindFinder rivista, es. "schilksee" windFinderSpotCollectionsList=Collezioni punti WindFinder @@ -2128,7 +2132,7 @@ automaticResizeNeedsStorageService=Per il ridimensionamento automatico occorre u qrCodeBoatInviteTitle=Sei invitato a tracciare la barca {0} per la regata {1} qrCodeMarkInviteTitle=Sei invitato a tracciare il segnale {0} per la regata {1} qrCodeCompetitorInviteTitle=Benvenuto {0} alla regata {1} -qrCodeTitleBouy=Benvenuto come {0} +qrCodeTitleBouy=Benvenuto come posaboe per la regata {0} qrCodeTitle=Benvenuto alla regata {0} qrCodeSubtitle={0} - {1} qrCodeTitleOpenRegatta=Benvenuto alla regata pubblica {0} @@ -2255,3 +2259,7 @@ editSwissTimingConnections=Modifica connessione SwissTiming filterSwissTimingConnections=Filtra connessioni SwissTiming addSwissTimingConnection=Aggiungi connessione SwissTiming updateURL=Aggiorna URL +startProcedure=Procedura di partenza +startMode=Modalità di partenza +gateOpeningTime=Ora di apertura del cancello +protestTimeInMinutes=Tempo per protesta (minuti) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ja.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ja.properties index c23bdaadcaf..4eccc94d08a 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ja.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ja.properties @@ -948,6 +948,7 @@ raceTimeUpwindTooltip=このレースでアップウィンドで移動した合 noCustomGrouperScriptTextError=分類スクリプトが空です noGrouperSelectedError=分類タイプが選択されていません dataMining=データマイニング +changeOrientation=方向の変更 hideToolbar=ツールバー非表示 showSeriesLeaderboards=シリーズリーダーボード表示 showOverallLeaderboard=全体リーダーボード表示 @@ -1051,8 +1052,10 @@ resultFromIgtimiWindImport=一覧されたレースに対して次の数のフ timeToStart=スタートまで {0} timeSinceStart=スタートから {0} distanceToLine=スタートラインまでの距離 -TWATooltip=競技者の方向と風の間のアングル +TWATooltip=競技者の対地コースと風の間のアングル (符号あり、マイナスの値は左舷からの風、プラスの値は右舷からの風を意味) +absoluteTWATooltip=競技者の対地コースと風の間のアングル (+/- 符号のないプラスの値) TWA=真の風角度 +absoluteTWA=絶対真風角度 showBoatClassChartsLabel=利用可能な艇種の全体図も表示することができます。 showDiagram=ダイアグラム表示 rerunQueryAfterRefreshTooltip=テーブルがリフレッシュされた後にクエリを再実行します。 @@ -1927,6 +1930,7 @@ finishingTime=フィニッシュ予定時刻 finishTimeString=フィニッシュ時刻 setFinishingAndFinishTime=フィニッシュ予定時刻とフィニッシュ時刻の設定 finishTimeMustBeAtOrAfterFinishingTime=フィニッシュ時刻はフィニッシュ予定時刻以降であることが必要 +youHaveToEnterAFinishingTimeIfYouEnterAFinishedTime=フィニッシュ時刻を入力する場合、フィニッシュ予定時刻を入力することが必要 boatNameMustNotBeEmpty=空でない艇名を指定してください errorUpdatingExpeditionDeviceConfiguration=Expedition デバイス設定 "{0}" の更新でエラーが発生: {1} doYouReallyWantToRemoveExpeditionDeviceConfiguration=Expedition デバイス設定 "{0}" を削除しますか @@ -2255,3 +2259,7 @@ editSwissTimingConnections=SwissTiming 接続の編集 filterSwissTimingConnections=SwissTiming 接続のフィルタリング addSwissTimingConnection=SwissTiming 接続の追加 updateURL=URL 更新 +startProcedure=スタート手順 +startMode=スタートモード +gateOpeningTime=ゲートオープニング時刻 +protestTimeInMinutes=抗議受付時間 (分) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_pt.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_pt.properties index d7de762d16d..8f820d69441 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_pt.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_pt.properties @@ -807,7 +807,7 @@ explainNoConnectionsFromReplicas=Nenhuma conexão de uma réplica encontrada. Vo stopConnectionToMaster=Parar replicação asLink=Como link noStarttimeAnnouncedYet=Pendente -raceIsRunning=Em execução +raceIsRunning=Em competição raceIsFinishing=Concluindo raceIsFinished=Concluído raceIsScheduled=Planejado @@ -948,6 +948,7 @@ raceTimeUpwindTooltip=Tempo total navegado a barlavento nesta corrida noCustomGrouperScriptTextError=O script do sistema de agrupamento está vazio noGrouperSelectedError=Nenhum tipo de sistema de agrupamento selecionado dataMining=Data mining +changeOrientation=Modificar orientação hideToolbar=Ocultar barra de ferramentas showSeriesLeaderboards=Visualizar painéis de classificação da série showOverallLeaderboard=Visualizar painel de classificação geral @@ -1051,8 +1052,10 @@ resultFromIgtimiWindImport=O número seguinte de pontos fixos foi importado para timeToStart={0} até partida timeSinceStart={0} desde partida distanceToLine=Distância para linha de partida -TWATooltip=O ângulo entre a direção dos competidores e o vento +TWATooltip=O ângulo entre o percurso no fundo dos competidores e o vento, assinalado, sendo os valores negativos vento de bombordo e os valores positivos vento de boreste +absoluteTWATooltip=O ângulo positivo entre o percurso no fundo dos competidores e o vento, sem sinal positivo/negativo TWA=Ângulo do vento verdadeiro +absoluteTWA=Ângulo do vento verdadeiro absoluto showBoatClassChartsLabel=Você também pode ver o diagrama geral para as classes de barcos disponíveis. showDiagram=Visualizar diagrama rerunQueryAfterRefreshTooltip=Executa novamente a consulta após a atualização das tabelas. @@ -1775,7 +1778,7 @@ couldNotSaveCompetitorRegistrations=Não foi possível gravar registros de compe searchTagForImportedCompetitorPlaceholder=Utilizar, por exemplo, corrida + nome da flotilha version=Versão: {0} replicables=Replicando objetos -set=Definir +set=Curso eventRegattaRacesLegendWind=# sensores de vento eventRegattaRacesLegendVideo=# fluxos de vídeo eventRegattaRacesLegendAudio=# fluxos de áudio @@ -1927,6 +1930,7 @@ finishingTime=Hora de chegada finishTimeString=Hora de conclusão setFinishingAndFinishTime=Definir hora de chegada e conclusão finishTimeMustBeAtOrAfterFinishingTime=A hora de conclusão deve ser igual ou posterior à hora de chegada +youHaveToEnterAFinishingTimeIfYouEnterAFinishedTime=Você precisa inserir uma hora de chegada se inserir uma hora de conclusão boatNameMustNotBeEmpty=Forneça um nome de barco não vazio errorUpdatingExpeditionDeviceConfiguration=Erro ao atualizar configuração de dispositivo Expedition "{0}": {1} doYouReallyWantToRemoveExpeditionDeviceConfiguration=Você quer realmente remover a configuração do dispositivo Expedition "{0}"? @@ -2114,7 +2118,7 @@ gender=Sexo manage2SailEventIdBox=ID de evento Manage2Sail manage2SailEventURLBox=URL de evento Manage2Sail (json) manage2SailEventIdBoxTooltip=ID de evento ou um URL que contenha o ID de evento do Manage2Sail -manage2SailPort=Porta +manage2SailPort=Bombordo audioFiles=Faixas de áudio selectMedia=Selecionar mídia swissTimingUpdateURL=Atualizar URL (por exemplo, para hora de partida e feedback de mudança de percurso) @@ -2255,3 +2259,7 @@ editSwissTimingConnections=Processar conexão SwissTiming filterSwissTimingConnections=Filtrar conexões SwissTiming addSwissTimingConnection=Adicionar conexão SwissTiming updateURL=Atualizar URL +startProcedure=Procedimento de partida +startMode=Modo de partida +gateOpeningTime=Hora de abertura do portão +protestTimeInMinutes=Tempo de protesto em minutos diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties index 6ecb7727ea7..21e7c591fc3 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties @@ -948,6 +948,7 @@ raceTimeUpwindTooltip=Общее время хода против ветра в noCustomGrouperScriptTextError=Скрипт группирования пуст noGrouperSelectedError=Не выбран тип группирования dataMining=Добыча данных +changeOrientation=Изменить ориентацию hideToolbar=Скрыть панель инструментов showSeriesLeaderboards=Показать таблицы лидеров серии showOverallLeaderboard=Показать итоговую таблицу лидеров @@ -1051,8 +1052,10 @@ resultFromIgtimiWindImport=Для перечисленных гонок импо timeToStart={0} до старта timeSinceStart={0} от старта distanceToLine=Дистанция до линии старта -TWATooltip=Угол между направлением участников и ветром +TWATooltip=Угол между курсом участников относительно грунта и ветром, со знаком, отрицательные значения означают ветер по левому борту, положительные - ветер по правому борту. +absoluteTWATooltip=участников относительно грунта и ветром, без знака +/- TWA=Угол истинного ветра +absoluteTWA=Абсолютный угол истинного ветра showBoatClassChartsLabel=Также можно просмотреть общую диаграмму для доступных классов лодок. showDiagram=Показать диаграмму rerunQueryAfterRefreshTooltip=Повторно выполняет запрос после обновления таблиц. @@ -1927,6 +1930,7 @@ finishingTime=Время финиширования finishTimeString=Время финиша setFinishingAndFinishTime=Указать время финиширования и финиша finishTimeMustBeAtOrAfterFinishingTime=Время финиша должно совпадать или быть после времени финиширования +youHaveToEnterAFinishingTimeIfYouEnterAFinishedTime=При вводе времени финиша необходимо ввести время финиширования boatNameMustNotBeEmpty=Укажите непустое имя лодки errorUpdatingExpeditionDeviceConfiguration=Ошибка при обновлении конфигурации устройства Expedition "{0}": {1} doYouReallyWantToRemoveExpeditionDeviceConfiguration=Действительно удалить конфигурацию устройства Expedition "{0}"? @@ -2255,3 +2259,7 @@ editSwissTimingConnections=Редактировать соединение Swiss filterSwissTimingConnections=Фильтр соединений SwissTiming addSwissTimingConnection=Добавить соединение SwissTiming updateURL=Обновить URL +startProcedure=Процедура старта +startMode=Режим старта +gateOpeningTime=Время открытия ворот +protestTimeInMinutes=Времени протеста в минутах diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties index c43ab88387a..8cb1492b656 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties @@ -696,9 +696,9 @@ speedOverGroundFiveSecondsBeforeStartTooltip=起航前五秒时的实际速度 speedOverGroundWhenPassingStartTooltip=参赛队越过起航线时的实际速度 startTack=开始迎风转向 startTackTooltip=参赛队开始迎风转向 -portTack=端口 +portTack=左舷 starboardTack=右舷 -portSide=端口 +portSide=左舷 starboardSide=右舷 pleaseEnterANumber=请输入数字。 competitorsFilter=参赛队筛选器 @@ -948,6 +948,7 @@ raceTimeUpwindTooltip=本轮次比赛迎风航行的总时间 noCustomGrouperScriptTextError=群集器脚本为空 noGrouperSelectedError=未选择群集器类型 dataMining=数据挖掘 +changeOrientation=更改方向 hideToolbar=隐藏工具栏 showSeriesLeaderboards=显示系列积分榜 showOverallLeaderboard=显示总积分榜 @@ -1051,8 +1052,10 @@ resultFromIgtimiWindImport=已为所列的比赛轮次导入以下修复: {0} timeToStart={0} - 开始 timeSinceStart={0} - 开始后 distanceToLine=与起航线的距离 -TWATooltip=赛队航行的方向和风的夹角 +TWATooltip=参赛队对地航向和风的夹角,设有符号标示,负值表示风来自左舷,正值表示风来自右舷 +absoluteTWATooltip=参赛队对地航向和风的正向夹角,不带 +/- 符号 TWA=实际风向角 +absoluteTWA=绝对实际风向角 showBoatClassChartsLabel=还可以查看可用船只级别的总直直方图。 showDiagram=显示直方图 rerunQueryAfterRefreshTooltip=在刷新表后,重新运行查询。 @@ -1927,6 +1930,7 @@ finishingTime=结束时间 finishTimeString=终点线时间 setFinishingAndFinishTime=设置结束和终点线时间 finishTimeMustBeAtOrAfterFinishingTime=终点线时间必须与结束时间相同或在其之后 +youHaveToEnterAFinishingTimeIfYouEnterAFinishedTime=如果输入终点线时间,则必须输入结束时间。 boatNameMustNotBeEmpty=请提供非空船只名称 errorUpdatingExpeditionDeviceConfiguration=更新导航图设备配置 "{0}" 出错:{1} doYouReallyWantToRemoveExpeditionDeviceConfiguration=是否确定移除导航图设备配置 "{0}"? @@ -2255,3 +2259,7 @@ editSwissTimingConnections=编辑 SwissTiming 连接 filterSwissTimingConnections=筛选 SwissTiming 连接 addSwissTimingConnection=添加 SwissTiming 连接 updateURL=更新 URL +startProcedure=起航程序 +startMode=起航模式 +gateOpeningTime=门标开启时间 +protestTimeInMinutes=声明时间(分钟) From 7daa5e2873d1dbde4cd3510cdeab37a8d7be4ea6 Mon Sep 17 00:00:00 2001 From: Robert Benedikt Date: Thu, 11 Jul 2019 12:51:25 +0200 Subject: [PATCH 63/69] Additionally persist the value set if a preference has changed that need to refresh its current values --- .../ui/fragments/preference/GeneralPreferenceFragment.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/preference/GeneralPreferenceFragment.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/preference/GeneralPreferenceFragment.java index c0fcc295200..5b3b404dd8d 100755 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/preference/GeneralPreferenceFragment.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/preference/GeneralPreferenceFragment.java @@ -33,6 +33,7 @@ import com.sap.sailing.racecommittee.app.utils.autoupdate.AutoUpdater; import java.io.FileNotFoundException; import java.util.Objects; +import java.util.Set; import java.util.UUID; public class GeneralPreferenceFragment extends BasePreferenceFragment { @@ -200,6 +201,7 @@ public class GeneralPreferenceFragment extends BasePreferenceFragment { //Update all the other preferences, e.g. course areas, mail recipient final SharedPreferences.OnSharedPreferenceChangeListener listener = new SharedPreferences.OnSharedPreferenceChangeListener() { + @SuppressWarnings("unchecked") @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { final Preference preference = findPreference(key); @@ -211,6 +213,9 @@ public class GeneralPreferenceFragment extends BasePreferenceFragment { if (listener != null) { listener.onPreferenceChange(preference, newValue); } + if (preference instanceof EditSetPreference) { + preference.persistStringSet((Set) newValue); + } } }; From 6fda79373de0ec03218f160ff55dc7728715b9ad Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Tue, 16 Jul 2019 12:19:48 +0200 Subject: [PATCH 64/69] bug5088: respect READ permission or lack thereof for result/competitor import URLs Change-Id: Ic0b21f6a698a69a363241671ec324114733deb7b --- .../gwt/ui/server/SailingServiceImpl.java | 14 +++------ .../META-INF/MANIFEST.MF | 4 +++ .../resultimport/ResultUrlRegistry.java | 29 +++++++++++++++++++ .../impl/ResultUrlRegistryImpl.java | 23 +++++++++++++-- .../release_notes_admin.html | 7 +++++ .../shared/AbstractUserGroupImpl.java | 5 ++-- 6 files changed, 67 insertions(+), 15 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index 8395fc3b387..e5c7f382d7c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java @@ -5209,19 +5209,13 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet @Override public List getResultImportUrls(String resultProviderName) { - List result = new ArrayList(); + final List result = new ArrayList(); ResultUrlProvider urlBasedScoreCorrectionProvider = getUrlBasedScoreCorrectionProvider(resultProviderName); ResultUrlRegistry resultUrlRegistry = getResultUrlRegistry(); if (urlBasedScoreCorrectionProvider != null) { - Iterable allUrls = resultUrlRegistry.getResultUrls(resultProviderName); - final Subject subject = SecurityUtils.getSubject(); - for (URL url : allUrls) { - if (subject - .isPermitted(SecuredDomainType.RESULT_IMPORT_URL.getStringPermissionForTypeRelativeIdentifier( - DefaultActions.READ, new TypeRelativeObjectIdentifier( - urlBasedScoreCorrectionProvider.getName(), url.toString())))) { - result.add(url.toString()); - } + Iterable allUrlsReadableBySubject = resultUrlRegistry.getResultUrls(resultProviderName); + for (URL url : allUrlsReadableBySubject) { + result.add(url.toString()); } } return result; diff --git a/java/com.sap.sailing.resultimport/META-INF/MANIFEST.MF b/java/com.sap.sailing.resultimport/META-INF/MANIFEST.MF index d1660d4b80e..c56c59907a5 100644 --- a/java/com.sap.sailing.resultimport/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.resultimport/META-INF/MANIFEST.MF @@ -12,8 +12,12 @@ Export-Package: com.sap.sailing.resultimport, com.sap.sailing.resultimport.impl Import-Package: com.sap.sailing.competitorimport, com.sap.sailing.domain.common, + com.sap.sailing.domain.common.security, com.sap.sailing.domain.persistence, com.sap.sailing.server.interfaces, + com.sap.sse.security.shared, + org.apache.shiro;version="1.2.2", + org.apache.shiro.subject;version="1.2.2", org.osgi.framework;version="1.5.0", org.osgi.util.tracker;version="1.5.1" Require-Bundle: com.sap.sse.common diff --git a/java/com.sap.sailing.resultimport/src/com/sap/sailing/resultimport/ResultUrlRegistry.java b/java/com.sap.sailing.resultimport/src/com/sap/sailing/resultimport/ResultUrlRegistry.java index 73243174f3e..7641c1e152a 100644 --- a/java/com.sap.sailing.resultimport/src/com/sap/sailing/resultimport/ResultUrlRegistry.java +++ b/java/com.sap.sailing.resultimport/src/com/sap/sailing/resultimport/ResultUrlRegistry.java @@ -2,14 +2,43 @@ package com.sap.sailing.resultimport; import java.net.URL; +import org.apache.shiro.subject.Subject; + +import com.sap.sailing.domain.common.security.SecuredDomainType; +import com.sap.sse.security.shared.HasPermissions.DefaultActions; + /** * A registry for result URL's of score correction providers * @author Frank */ public interface ResultUrlRegistry { + /** + * Registers the URL {@code url} for the result provider named {@code resultProviderName}. Unlike the + * {@link #getResultUrls(String)} method, here no security check is performed. The caller is expected to assert that + * the calling {@link Subject} has the permission {@link SecuredDomainType#RESULT_IMPORT_URL + * RESULT_IMPORT_URL}.{@link DefaultActions#CREATE CREATE} after setting the ownership. Implementing this + * check properly is done best with the {@code SecurityService} which is not visible from this bundle. + */ void registerResultUrl(String resultProviderName, URL url); + + /** + * Registers the URL {@code url} from the result provider named {@code resultProviderName}. Unlike the + * {@link #getResultUrls(String)} method, here no security check is performed. The caller is expected to assert that + * the calling {@link Subject} has the permission {@link SecuredDomainType#RESULT_IMPORT_URL + * RESULT_IMPORT_URL}.{@link DefaultActions#DELETE DELETE} after setting the ownership. Implementing this + * check properly is done best with the {@code SecurityService} which is not visible from this bundle. + */ void unregisterResultUrl(String resultProviderName, URL url); + /** + * Obtains the result import URLs registered for the provider named {@code resultProviderName}. If no such URLs are + * found, an empty iterable is returned. The URLs returned are filtered by the calling {@link Subject}'s permission + * to The URLs returned are filtered by the calling {@link Subject}'s permission + * to {@link SecuredDomainType#RESULT_IMPORT_URL RESULT_IMPORT_URL}.{@link DefaultActions#READ READ} them. them. + * + * @return an always valid, non-{@code null} iterable + */ Iterable getResultUrls(String resultProviderName); + Iterable getResultProviderNames(); } diff --git a/java/com.sap.sailing.resultimport/src/com/sap/sailing/resultimport/impl/ResultUrlRegistryImpl.java b/java/com.sap.sailing.resultimport/src/com/sap/sailing/resultimport/impl/ResultUrlRegistryImpl.java index b57ee771e9f..3273b01beb5 100644 --- a/java/com.sap.sailing.resultimport/src/com/sap/sailing/resultimport/impl/ResultUrlRegistryImpl.java +++ b/java/com.sap.sailing.resultimport/src/com/sap/sailing/resultimport/impl/ResultUrlRegistryImpl.java @@ -1,14 +1,22 @@ package com.sap.sailing.resultimport.impl; import java.net.URL; +import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; +import java.util.Iterator; import java.util.Map; import java.util.Set; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.subject.Subject; + +import com.sap.sailing.domain.common.security.SecuredDomainType; import com.sap.sailing.domain.persistence.DomainObjectFactory; import com.sap.sailing.domain.persistence.MongoObjectFactory; import com.sap.sailing.resultimport.ResultUrlRegistry; +import com.sap.sse.security.shared.HasPermissions.DefaultActions; +import com.sap.sse.security.shared.TypeRelativeObjectIdentifier; public class ResultUrlRegistryImpl implements ResultUrlRegistry { private final Map> resultUrls; @@ -41,9 +49,18 @@ public class ResultUrlRegistryImpl implements ResultUrlRegistry { @Override public Iterable getResultUrls(String resultProviderName) { - Iterable result; - if(resultUrls.containsKey(resultProviderName)) { - result = resultUrls.get(resultProviderName); + final Subject subject = SecurityUtils.getSubject(); + final Iterable result; + if (resultUrls.containsKey(resultProviderName)) { + result = new ArrayList<>(resultUrls.get(resultProviderName)); + for (final Iterator urlIterator = result.iterator(); urlIterator.hasNext();) { + final URL url = urlIterator.next(); + if (!subject.isPermitted(SecuredDomainType.RESULT_IMPORT_URL + .getStringPermissionForTypeRelativeIdentifier(DefaultActions.READ, + new TypeRelativeObjectIdentifier(resultProviderName, url.toString())))) { + urlIterator.remove(); + } + } } else { result = Collections.emptySet(); } diff --git a/java/com.sap.sailing.www/release_notes_admin.html b/java/com.sap.sailing.www/release_notes_admin.html index c2d29440fa0..38e92e1ffeb 100755 --- a/java/com.sap.sailing.www/release_notes_admin.html +++ b/java/com.sap.sailing.www/release_notes_admin.html @@ -21,6 +21,12 @@

        Release Notes - Administration Console

        +

        July 2019

        +
          +
        • Result and competitor import URLs are now only considered when the requesting user + has the permission to read that URL.
        • +
        +

        June 2019

        • Added new API endpoints for creating, reading, updating and deleting roles under /restsecurity/role. @@ -36,6 +42,7 @@
        • Users can now create media tracks if they have the permissions based on the ownership that will result from the creation process.
        +

        May 2019

        • Ranks (finishing orders) entered by the Race Manager app user are no longer diff --git a/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/AbstractUserGroupImpl.java b/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/AbstractUserGroupImpl.java index a1c84ec0f55..57f28d706c4 100644 --- a/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/AbstractUserGroupImpl.java +++ b/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/AbstractUserGroupImpl.java @@ -4,6 +4,8 @@ import java.util.Map; import java.util.Set; import java.util.UUID; +import com.sap.sse.common.Util; + /** * A group of users; equality and hash code are based solely on the {@link #getId() ID}. */ @@ -45,7 +47,6 @@ public abstract class AbstractUserGroupImpl Date: Tue, 16 Jul 2019 14:23:50 +0200 Subject: [PATCH 65/69] Added a more accurate implementation for the Duration interface. --- .../domain/common/test/DurationTest.java | 19 +++- .../sse/common/impl/SecondsDurationImpl.java | 107 ++++++++++++++++++ 2 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 java/com.sap.sse.common/src/com/sap/sse/common/impl/SecondsDurationImpl.java diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/DurationTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/DurationTest.java index 9c56800ef26..3ee5ed38580 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/DurationTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/DurationTest.java @@ -13,6 +13,7 @@ import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; import com.sap.sse.common.impl.MillisecondsDurationImpl; import com.sap.sse.common.impl.MillisecondsTimePoint; +import com.sap.sse.common.impl.SecondsDurationImpl; public class DurationTest { @Test @@ -88,7 +89,7 @@ public class DurationTest { } @Test - public void testOperations() { + public void testOperationsMilliseconds() { Duration someSeconds = new MillisecondsDurationImpl(2400).minus(1000); assertEquals(0, someSeconds.asDays(), 0.1); assertEquals(0, someSeconds.asHours(), 0.1); @@ -102,6 +103,22 @@ public class DurationTest { assertEquals(3600*25, oneDay.asSeconds(), 0.1); assertEquals(3600*25*1000, oneDay.asMillis()); } + + @Test + public void testOperationsSeconds() { + Duration someSeconds = new SecondsDurationImpl(2.4).minus(1000); + assertEquals(0, someSeconds.asDays(), 0.1); + assertEquals(0, someSeconds.asHours(), 0.1); + assertEquals(0, someSeconds.asMinutes(), 0.1); + assertEquals(1.4, someSeconds.asSeconds(), 0.1); + assertEquals(1400, someSeconds.asMillis(), 0.1); + Duration oneDay = Duration.ONE_DAY.plus(Duration.ONE_HOUR); + assertEquals(25, oneDay.asHours(), 0.001); + assertEquals(1, oneDay.asDays(), 0.01); + assertEquals(25*60, oneDay.asMinutes(), 0.1); + assertEquals(3600*25, oneDay.asSeconds(), 0.1); + assertEquals(3600*25*1000, oneDay.asMillis()); + } @Test public void compare() { diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/impl/SecondsDurationImpl.java b/java/com.sap.sse.common/src/com/sap/sse/common/impl/SecondsDurationImpl.java new file mode 100644 index 00000000000..33c318f68ef --- /dev/null +++ b/java/com.sap.sse.common/src/com/sap/sse/common/impl/SecondsDurationImpl.java @@ -0,0 +1,107 @@ +package com.sap.sse.common.impl; + +import com.sap.sse.common.Duration; + +/** + * Uses double for internal representation. Therefore this implementation achieves a higher accuracy but uses more + * memory in comparison to {@link MillisecondsDurationImpl}. + * + * @author Daniel Lisunkin (i505543) + * + */ +public class SecondsDurationImpl implements Duration { + private static final long serialVersionUID = 7575912908654324216L; + private final double seconds; + + public SecondsDurationImpl(double seconds) { + super(); + this.seconds = seconds; + } + + @Override + public int compareTo(Duration o) { + double diff = seconds - o.asSeconds(); + return diff > 0. ? 1 : diff < 0. ? -1 : 0; + } + + @Override + public long asMillis() { + return Math.round(seconds / Duration.ONE_MILLISECOND.asSeconds()); + } + + @Override + public double asSeconds() { + return seconds; + } + + @Override + public double asMinutes() { + return seconds / Duration.ONE_MINUTE.asSeconds(); + } + + @Override + public double asHours() { + return seconds / Duration.ONE_HOUR.asSeconds(); + } + + @Override + public double asDays() { + return seconds / Duration.ONE_DAY.asSeconds(); + } + + @Override + public Duration abs() { + return seconds >= 0 ? this : new SecondsDurationImpl(-seconds); + } + + @Override + public Duration divide(long divisor) { + return new SecondsDurationImpl(seconds / divisor); + } + + @Override + public Duration divide(double divisor) { + return new SecondsDurationImpl(seconds / divisor); + } + + @Override + public double divide(Duration duration) { + return (seconds / duration.asSeconds()); + } + + @Override + public Duration times(long factor) { + return new SecondsDurationImpl(seconds * factor); + } + + @Override + public Duration times(double factor) { + return new SecondsDurationImpl(seconds * factor); + } + + @Override + public Duration minus(Duration duration) { + return new SecondsDurationImpl(seconds - duration.asSeconds()); + } + + @Override + public Duration minus(long milliseconds) { + return new SecondsDurationImpl(seconds - (double) milliseconds / 1000.); + } + + @Override + public Duration plus(long milliseconds) { + return new SecondsDurationImpl(seconds + milliseconds / 1000.); + } + + @Override + public Duration plus(Duration duration) { + return new SecondsDurationImpl(seconds + duration.asSeconds()); + } + + @Override + public Duration mod(Duration d) { + return new SecondsDurationImpl(seconds % d.asSeconds()); + } + +} From 71fa06b77e96174a4534af70379f0207f8f6360d Mon Sep 17 00:00:00 2001 From: Daniel Lisunkin Date: Tue, 16 Jul 2019 17:29:35 +0200 Subject: [PATCH 66/69] Changes in AbstractDistance implementation to achieve a higher accuracy when calculating velocities. --- .../src/com/sap/sailing/domain/common/AbstractDistance.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/AbstractDistance.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/AbstractDistance.java index 19b15315250..1dadc966d12 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/AbstractDistance.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/AbstractDistance.java @@ -27,6 +27,10 @@ public abstract class AbstractDistance implements Distance { return meters > otherMeters ? 1 : meters == otherMeters ? 0 : -1; } + private Speed inSeconds(double seconds) { + return new KilometersPerHourSpeedImpl(getKilometers() * 3600 / seconds); + } + @Override public Speed inTime(long milliseconds) { return new KilometersPerHourSpeedImpl(getKilometers() * 1000. * 3600. / milliseconds); @@ -34,7 +38,7 @@ public abstract class AbstractDistance implements Distance { @Override public Speed inTime(Duration duration) { - return inTime(duration.asMillis()); + return inSeconds(duration.asSeconds()); } @Override From 47a4780454ba5453c029044ba630bad92aa99650 Mon Sep 17 00:00:00 2001 From: Daniel Lisunkin Date: Tue, 16 Jul 2019 17:32:20 +0200 Subject: [PATCH 67/69] Added toString() method do SecondsDurationImpl. --- .../src/com/sap/sse/common/impl/SecondsDurationImpl.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/impl/SecondsDurationImpl.java b/java/com.sap.sse.common/src/com/sap/sse/common/impl/SecondsDurationImpl.java index 33c318f68ef..900d1824a2c 100644 --- a/java/com.sap.sse.common/src/com/sap/sse/common/impl/SecondsDurationImpl.java +++ b/java/com.sap.sse.common/src/com/sap/sse/common/impl/SecondsDurationImpl.java @@ -103,5 +103,12 @@ public class SecondsDurationImpl implements Duration { public Duration mod(Duration d) { return new SecondsDurationImpl(seconds % d.asSeconds()); } + + @Override + public String toString() { + StringBuffer result = new StringBuffer(); + result.append(asSeconds()).append("s"); + return result.toString(); + } } From 7bef35811e9e01d2c36e172c329cd952c32f1319 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Wed, 17 Jul 2019 11:39:30 +0200 Subject: [PATCH 68/69] Bug 4960: removed enrichment of the events received from TrackedEventsResource --- .../jaxrs/api/TrackedEventsResource.java | 38 ------------------- 1 file changed, 38 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index ce8914b3045..1c13c74af26 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -3,7 +3,6 @@ package com.sap.sailing.server.gateway.jaxrs.api; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; -import java.util.List; import java.util.UUID; import java.util.function.Function; import java.util.stream.Collectors; @@ -29,7 +28,6 @@ import org.json.simple.JSONObject; import org.json.simple.JSONValue; import org.json.simple.parser.ParseException; -import com.sap.sailing.domain.base.Event; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.impl.Helpers; import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource; @@ -37,10 +35,7 @@ import com.sap.sailing.server.impl.preferences.model.SailingPreferences; import com.sap.sailing.server.impl.preferences.model.TrackedElementWithDeviceId; import com.sap.sailing.server.impl.preferences.model.TrackedEventPreference; import com.sap.sailing.server.impl.preferences.model.TrackedEventPreferences; -import com.sap.sse.common.media.MediaTagConstants; -import com.sap.sse.security.shared.OwnershipAnnotation; import com.sap.sse.security.shared.impl.User; -import com.sap.sse.shared.media.ImageDescriptor; @Path("/v1/trackedevents/") public class TrackedEventsResource extends AbstractSailingServerResource { @@ -50,13 +45,8 @@ public class TrackedEventsResource extends AbstractSailingServerResource { private static final String KEY_LEADERBOARD_NAME = "leaderboardName"; private static final String KEY_EVENT_ID = "eventId"; private static final String KEY_EVENT_IS_ARCHIVED = "isArchived"; - private static final String KEY_EVENT_NAME = "name"; - private static final String KEY_EVENT_START = "start"; - private static final String KEY_EVENT_END = "end"; private static final String KEY_EVENT_TRACKED_ELEMENTS = "trackedElements"; private static final String KEY_EVENT_BASE_URL = "url"; - private static final String KEY_EVENT_IS_OWNER = "isOwner"; - private static final String KEY_EVENT_IMAGE_URL = "imageUrl"; private static final String KEY_EVENT_REGATTA_SECRET = "regattaSecret"; private static final String KEY_TRACKED_ELEMENT_DEVICE_ID = "deviceId"; private static final String KEY_TRACKED_ELEMENT_COMPETITOR_ID = "competitorId"; @@ -90,35 +80,7 @@ public class TrackedEventsResource extends AbstractSailingServerResource { continue; } - final UUID eventId = pref.getEventId(); - final Event event = getService().getEvent(eventId); final JSONObject jsonEvent = new JSONObject(); - if (event != null) { - // event actually exists on this server -> parse relevant data - if (getSecurityService().hasCurrentUserReadPermission(event)) { - // user has read permission on event -> add additional event-specific data - final OwnershipAnnotation ownership = getSecurityService() - .getOwnership(event.getIdentifier()); - final boolean isOwner = currentUser == null ? false - : currentUser.equals(ownership.getAnnotation().getUserOwner()); - jsonEvent.put(KEY_EVENT_IS_OWNER, isOwner); - - jsonEvent.put(KEY_EVENT_NAME, event.getName()); - jsonEvent.put(KEY_EVENT_START, event.getStartDate().toString()); - jsonEvent.put(KEY_EVENT_END, event.getEndDate().toString()); - - final List imageWithLogoTag = event - .findImagesWithTag(MediaTagConstants.LOGO.getName()); - if (!imageWithLogoTag.isEmpty()) { - jsonEvent.put(KEY_EVENT_IMAGE_URL, imageWithLogoTag.get(0).getURL().toExternalForm()); - } else { - // user does not have read permissions for this event on this server -> only send back - // basic data - } - } - } else { - // event does not exist on this server --> only send back basic data - } jsonEvent.put(KEY_EVENT_ID, pref.getEventId().toString()); jsonEvent.put(KEY_EVENT_REGATTA_SECRET, pref.getRegattaSecret()); jsonEvent.put(KEY_EVENT_BASE_URL, pref.getBaseUrl()); From e3ac96c203f248337d6904e58b0b890edb47e1b4 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Wed, 17 Jul 2019 12:00:40 +0200 Subject: [PATCH 69/69] Bug 5089: fixed refresh issue which could lead to data leak in ResultImportUrls panel. --- .../gwt/ui/adminconsole/AdminConsoleEntryPoint.java | 9 ++++++++- .../ui/adminconsole/ResultImportUrlsManagementPanel.java | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java index 9a2f2ace2be..3af2d3c950a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java @@ -357,7 +357,14 @@ public class AdminConsoleEntryPoint extends AbstractSailingEntryPoint ResultImportUrlsManagementPanel resultImportUrlsManagementPanel = new ResultImportUrlsManagementPanel( getSailingService(), getUserService(), this, getStringMessages()); - panel.addToTabPanel(connectorsTabPanel, new DefaultRefreshableAdminConsolePanel(resultImportUrlsManagementPanel), + panel.addToTabPanel(connectorsTabPanel, + new DefaultRefreshableAdminConsolePanel( + resultImportUrlsManagementPanel) { + @Override + public void refreshAfterBecomingVisible() { + resultImportUrlsManagementPanel.refreshUrlList(); + } + }, getStringMessages().resultImportUrls(), SecuredDomainType.RESULT_IMPORT_URL.getPermission(DefaultActions.values())); StructureImportManagementPanel structureImportUrlsManagementPanel = new StructureImportManagementPanel( diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ResultImportUrlsManagementPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ResultImportUrlsManagementPanel.java index b41c919c03e..ce605b85230 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ResultImportUrlsManagementPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ResultImportUrlsManagementPanel.java @@ -107,7 +107,7 @@ public class ResultImportUrlsManagementPanel extends FlowPanel { return result; } - private void refreshUrlList() { + public void refreshUrlList() { String selectedProviderName = getSelectedProviderName(); if (selectedProviderName != null) { sailingService.getResultImportUrls(selectedProviderName, new AsyncCallback>() {