2c6d25a18d72bd4a234f2ea9e19d4d631b2777a0
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/IgtimiDevicesPanel.java
| ... | ... | @@ -20,6 +20,7 @@ import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler; |
| 20 | 20 | import com.google.gwt.user.cellview.client.TextColumn; |
| 21 | 21 | import com.google.gwt.user.client.Window; |
| 22 | 22 | import com.google.gwt.user.client.rpc.AsyncCallback; |
| 23 | +import com.google.gwt.user.client.ui.Anchor; |
|
| 23 | 24 | import com.google.gwt.user.client.ui.Button; |
| 24 | 25 | import com.google.gwt.user.client.ui.CaptionPanel; |
| 25 | 26 | import com.google.gwt.user.client.ui.FlowPanel; |
| ... | ... | @@ -40,6 +41,7 @@ import com.sap.sailing.gwt.ui.client.StringMessages; |
| 40 | 41 | import com.sap.sailing.gwt.ui.shared.IgtimiDataAccessWindowWithSecurityDTO; |
| 41 | 42 | import com.sap.sailing.gwt.ui.shared.IgtimiDeviceWithSecurityDTO; |
| 42 | 43 | import com.sap.sse.common.Util; |
| 44 | +import com.sap.sse.common.Util.Pair; |
|
| 43 | 45 | import com.sap.sse.gwt.adminconsole.AdminConsoleTableResources; |
| 44 | 46 | import com.sap.sse.gwt.adminconsole.FilterablePanelProvider; |
| 45 | 47 | import com.sap.sse.gwt.client.ErrorReporter; |
| ... | ... | @@ -69,12 +71,7 @@ import com.sap.sse.security.ui.client.component.SecuredDTOOwnerColumn; |
| 69 | 71 | import com.sap.sse.security.ui.client.component.editacl.EditACLDialog; |
| 70 | 72 | |
| 71 | 73 | /** |
| 72 | - * TODO bug 6059: implement a second table shown when a single device is selected in the devices table that shows the |
|
| 73 | - * data access windows for that device; alternatively we could show all data access windows for all devices when nothing |
|
| 74 | - * is selected. Move the "Add" button from devices to DAWs. |
|
| 75 | - * |
|
| 76 | 74 | * @author Axel Uhl (d043530) |
| 77 | - * |
|
| 78 | 75 | */ |
| 79 | 76 | public class IgtimiDevicesPanel extends FlowPanel implements FilterablePanelProvider<IgtimiDeviceWithSecurityDTO> { |
| 80 | 77 | private final StringMessages stringMessages; |
| ... | ... | @@ -113,6 +110,27 @@ public class IgtimiDevicesPanel extends FlowPanel implements FilterablePanelProv |
| 113 | 110 | this.errorReporter = presenter.getErrorReporter(); |
| 114 | 111 | this.stringMessages = stringMessages; |
| 115 | 112 | final AdminConsoleTableResources tableRes = GWT.create(AdminConsoleTableResources.class); |
| 113 | + final Label igtimiConnectionFactoryParams = new Label(); |
|
| 114 | + final Anchor linkToRemoteRiotAdminPanel = new Anchor(stringMessages.configuration(), (String) null, /* target */ "_blank"); |
|
| 115 | + final HorizontalPanel remoteRiotConfig = new HorizontalPanel(); |
|
| 116 | + remoteRiotConfig.setSpacing(5); |
|
| 117 | + remoteRiotConfig.add(igtimiConnectionFactoryParams); |
|
| 118 | + remoteRiotConfig.add(linkToRemoteRiotAdminPanel); |
|
| 119 | + add(remoteRiotConfig); |
|
| 120 | + add(new Label(stringMessages.localServer())); |
|
| 121 | + sailingServiceWrite.getIgtimiConnectionFactoryBaseUrl(new AsyncCallback<Pair<String, Boolean>>() { |
|
| 122 | + @Override |
|
| 123 | + public void onFailure(Throwable caught) { |
|
| 124 | + Notification.notify(stringMessages.errorGettingIgtimiConnectionFactoryParams(caught.getMessage()), NotificationType.ERROR); |
|
| 125 | + } |
|
| 126 | + |
|
| 127 | + @Override |
|
| 128 | + public void onSuccess(Pair<String, Boolean> result) { |
|
| 129 | + igtimiConnectionFactoryParams.setText(stringMessages.igtimiConnectionFactoryParams(result.getA(), |
|
| 130 | + result.getB() ? stringMessages.yes() : stringMessages.no())); |
|
| 131 | + linkToRemoteRiotAdminPanel.setHref(result.getA()+"/gwt/AdminConsole.html#IgtimiDevicesPlace:"); |
|
| 132 | + } |
|
| 133 | + }); |
|
| 116 | 134 | // setup devices table |
| 117 | 135 | final CaptionPanel devicesCaptionPanel = new CaptionPanel(stringMessages.igtimiDevices()); |
| 118 | 136 | final VerticalPanel devicesCaptionPanelContents = new VerticalPanel(); |
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java
| ... | ... | @@ -493,7 +493,9 @@ public interface SailingService extends RemoteService, RemoteReplicationService |
| 493 | 493 | ArrayList<IgtimiDeviceWithSecurityDTO> getAllIgtimiDevicesWithSecurity() throws Exception; |
| 494 | 494 | |
| 495 | 495 | ArrayList<IgtimiDataAccessWindowWithSecurityDTO> getAllIgtimiDataAccessWindowsWithSecurity() throws Exception; |
| 496 | - |
|
| 496 | + |
|
| 497 | + Pair<String, Boolean> getIgtimiConnectionFactoryBaseUrl(); |
|
| 498 | + |
|
| 497 | 499 | /** |
| 498 | 500 | * Allows reading public Boats, or Boats that are registered in races belonging in the given regatta |
| 499 | 501 | */ |
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java
| ... | ... | @@ -546,6 +546,8 @@ public interface SailingServiceAsync extends RemoteReplicationServiceAsync { |
| 546 | 546 | |
| 547 | 547 | void getAllIgtimiDataAccessWindowsWithSecurity(AsyncCallback<ArrayList<IgtimiDataAccessWindowWithSecurityDTO>> callback); |
| 548 | 548 | |
| 549 | + void getIgtimiConnectionFactoryBaseUrl(AsyncCallback<Pair<String, Boolean>> callback); |
|
| 550 | + |
|
| 549 | 551 | /** |
| 550 | 552 | * Allows reading public Boats, or Boats that are registered in races belonging in the given regatta |
| 551 | 553 | */ |
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java
| ... | ... | @@ -2472,4 +2472,6 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, |
| 2472 | 2472 | String endOfRepeatablePartMustBeAtOfAfterStart(); |
| 2473 | 2473 | String endOfRepeatablePartIsGreaterThanNumberOfWaypoints(); |
| 2474 | 2474 | String configureCourse(); |
| 2475 | + String errorGettingIgtimiConnectionFactoryParams(String message); |
|
| 2476 | + String igtimiConnectionFactoryParams(String baseUrl, String hasCredentialsYesOrNo); |
|
| 2475 | 2477 | } |
| ... | ... | \ No newline at end of file |
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties
| ... | ... | @@ -2508,4 +2508,6 @@ defaultNumberOfLapsMustNotBeNegative=Default number of laps must not be negative |
| 2508 | 2508 | eitherNoneOrBothStartAndEndOfRepeatablePartMustBeSpecified=Either none or both, start and end, of the repeatable part of the waypoint sequence must be specified. |
| 2509 | 2509 | endOfRepeatablePartMustBeAtOfAfterStart=End of repeatable part must be at or after start of repeatable part. |
| 2510 | 2510 | endOfRepeatablePartIsGreaterThanNumberOfWaypoints=End of repeatable part is greater than number of waypoints. |
| 2511 | -configureCourse=Configure Course |
|
| ... | ... | \ No newline at end of file |
| 0 | +configureCourse=Configure Course |
|
| 1 | +errorGettingIgtimiConnectionFactoryParams=Error getting Igtimi connection factory parameters: {0} |
|
| 2 | +igtimiConnectionFactoryParams=Igtimi connection factory parameters: Base URL is {0}, credentials provided: {1} |
|
| ... | ... | \ No newline at end of file |
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties
| ... | ... | @@ -2502,4 +2502,6 @@ defaultNumberOfLapsMustNotBeNegative=Standard-Rundenzahl darf nicht negativ sein |
| 2502 | 2502 | eitherNoneOrBothStartAndEndOfRepeatablePartMustBeSpecified=Anfang und Ende der wiederholbaren Wegpunkte-Sequenz müssen entweder beide gesetzt oder beide leer sein. |
| 2503 | 2503 | endOfRepeatablePartMustBeAtOfAfterStart=Ende der wiederholbaren Wegpunkte-Sequenz muss auf oder nach dem Anfang liegen. |
| 2504 | 2504 | endOfRepeatablePartIsGreaterThanNumberOfWaypoints=Ende der wiederholbaren Wegpunkte-Sequenz liegt hinter dem Ende der Wegpunkt-Liste. |
| 2505 | -configureCourse=Kurs konfigurieren |
|
| ... | ... | \ No newline at end of file |
| 0 | +configureCourse=Kurs konfigurieren |
|
| 1 | +errorGettingIgtimiConnectionFactoryParams=Fehler beim Laden der Igtimi Verbindungsparameter: {0} |
|
| 2 | +igtimiConnectionFactoryParams=Igtimi Server: {0}, Benutzer-Authentifizierungsdaten vorhanden: {1} |
|
| ... | ... | \ No newline at end of file |
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java
| ... | ... | @@ -4240,6 +4240,12 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet |
| 4240 | 4240 | } |
| 4241 | 4241 | |
| 4242 | 4242 | @Override |
| 4243 | + public Pair<String, Boolean> getIgtimiConnectionFactoryBaseUrl() { |
|
| 4244 | + final IgtimiConnectionFactory igtimiConnectionFactory = getIgtimiConnectionFactory(); |
|
| 4245 | + return new Pair<>(igtimiConnectionFactory.getBaseUrl().toString(), igtimiConnectionFactory.hasCredentials()); |
|
| 4246 | + } |
|
| 4247 | + |
|
| 4248 | + @Override |
|
| 4243 | 4249 | public ArrayList<IgtimiDeviceWithSecurityDTO> getAllIgtimiDevicesWithSecurity() throws IllegalStateException, ClientProtocolException, IOException, org.json.simple.parser.ParseException { |
| 4244 | 4250 | final Map<String, TimePoint> lastHeartBeatsByDeviceSerialNumber = new HashMap<>(); |
| 4245 | 4251 | final Map<String, SocketAddress> remoteAddressByDeviceSerialNumber = new HashMap<>(); |
java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/procedures/SailingProcessConfigurationVariables.java
| ... | ... | @@ -14,5 +14,20 @@ public enum SailingProcessConfigurationVariables implements ProcessConfiguration |
| 14 | 14 | * a typical port would be 6000 which is the default for the WindBot devices. If not specified, the |
| 15 | 15 | * Riot server will listen on any available, unused server port. Maps to the igtimi.riot.port property. |
| 16 | 16 | */ |
| 17 | - IGTIMI_RIOT_PORT; |
|
| 17 | + IGTIMI_RIOT_PORT, |
|
| 18 | + |
|
| 19 | + /** |
|
| 20 | + * Use this variable to override the default {@code https://wind.sapsailing.com} base URL for obtaining |
|
| 21 | + * wind data from Igtimi devices. Authentication to this service by default will assume shared security |
|
| 22 | + * and therefore shared user bases with shared access tokens. If this does not apply to your set-up, |
|
| 23 | + * consider using {@link #IGTIMI_BEARER_TOKEN} in addition. |
|
| 24 | + */ |
|
| 25 | + IGTIMI_BASE_URL, |
|
| 26 | + |
|
| 27 | + /** |
|
| 28 | + * Overrides the default authentication scheme for requests against the remote "Riot" service for Igtimi |
|
| 29 | + * wind connectivity whose base URL may be overridden using {@link #IGTIMI_BASE_URL}. Specify a bearer token |
|
| 30 | + * valid in the context of the security service of the remote Riot service. |
|
| 31 | + */ |
|
| 32 | + IGTIMI_BEARER_TOKEN; |
|
| 18 | 33 | } |
java/com.sap.sailing.www/release_notes_admin.html
| ... | ... | @@ -35,14 +35,36 @@ |
| 35 | 35 | environment variable set for the <tt>start</tt> script. When left empty, |
| 36 | 36 | the Riot server will listen on a random port unused so far. This port can |
| 37 | 37 | be obtained using the <tt>/igtimi/api/v1/server</tt> REST GET method, found |
| 38 | - in the <tt>port</tt> attribute of the JSON document responded with.<p> |
|
| 38 | + in the <tt>port</tt> attribute of the JSON document responded with. |
|
| 39 | + The built-in Riot server is replicated by default, and devices and data access |
|
| 40 | + windows are kept synchronized between primary and replicas. Dedicated instances |
|
| 41 | + may be set up with the only purpose of acting as a highly-available Riot server |
|
| 42 | + farm. Messages sent to one of the instances in the replica set will make it to |
|
| 43 | + all instances in the replica set and will eventually get stored persistently in |
|
| 44 | + the primary's database. |
|
| 45 | + <p> |
|
| 39 | 46 | Devices can be configured to send to that port, directly to the server's IP |
| 40 | 47 | address with the specific port, or, e.g., through a network load balancer |
| 41 | 48 | such as the Amazon Web Services (AWS) NLB, allowing for multiple servers |
| 42 | 49 | such as a primary/master and one or more replicas to be registered for |
| 43 | 50 | high availability. With an AWS NLB it is important to configure the target group |
| 44 | 51 | such that the client IP address is preserved, so the server knows where to send |
| 45 | - responses and commands to.<p> |
|
| 52 | + responses and commands to. |
|
| 53 | + <p> |
|
| 54 | + Instead of managing Igtimi "Accounts" there now is a system property <tt>igtimi.base.url</tt> |
|
| 55 | + that defines the base URL of the Riot service to which the Sailing Analytics server will |
|
| 56 | + connect for live and stored WindBot data. The new environment variable <tt>IGTIMI_BASE_URL</tt> |
|
| 57 | + is mapped to the <tt>igtimi.base.url</tt> property in the start scripts. |
|
| 58 | + The property defaults to <tt>https://wind.sapsailing.com</tt>. |
|
| 59 | + By default, authentication for the remote service is handled using the local user's bearer token |
|
| 60 | + of the user tracking or owning the race for which wind data is requested. The <tt>igtimi.bearer.token</tt> |
|
| 61 | + system property can be used as an override, e.g., in case the local Sailing Analytics server |
|
| 62 | + does not share the security service with the replica set running the Riot service. The corresponding |
|
| 63 | + environment variable is <tt>IGTIMI_BEARER_TOKEN</tt>. With this, |
|
| 64 | + the <tt>igtimi.client.id</tt> and <tt>igtimi.client.secret</tt> system properties, as well as |
|
| 65 | + their environment variable counterparts <tt>IGTIMI_CLIENT_ID</tt> and <tt>IGTIMI_CLIENT_SECRET</tt>, |
|
| 66 | + respectively, are no longer used. |
|
| 67 | + <p> |
|
| 46 | 68 | The new version of the Igtimi Devices panel in the Admin Console (see |
| 47 | 69 | <tt>/gwt/AdminConsole.html#IgtimiDevicesPlace:</tt>) now shows the devices |
| 48 | 70 | and their sharing to clients through so-called "Data Access Windows." The |
| ... | ... | @@ -52,7 +74,8 @@ |
| 52 | 74 | the DAWs' ownership and access control list (ACL) settings and grant users |
| 53 | 75 | explicit permissions to individual DAWs. Click on the "Change Ownership" action icon |
| 54 | 76 | to see the key of a DAW in case you want to use it in an individual permission |
| 55 | - that you grant to a user.<p> |
|
| 77 | + that you grant to a user. |
|
| 78 | + <p> |
|
| 56 | 79 | There is a REST API that mimics the old Riot REST API to a certain degree. |
| 57 | 80 | Sailing Analytics users and operators typically don't work with this API directly. |
| 58 | 81 | Yet, the API is exposed under <tt>/igtimi/api/v1</tt> and has end points for |
| ... | ... | @@ -60,11 +83,13 @@ |
| 60 | 83 | as well as for finding out the web socket server end |
| 61 | 84 | point for connecting to live data and connecting to it, |
| 62 | 85 | and the above-mentioned method for finding |
| 63 | - out the Riot server socket's listening port.<p> |
|
| 86 | + out the Riot server socket's listening port. |
|
| 87 | + <p> |
|
| 64 | 88 | The protocol used for transmitting device data to REST API clients has changed in |
| 65 | 89 | so far that the device message payloads are no longer sent as JSON objects; instead, |
| 66 | 90 | the original Protocol Buffer (protobuf) binary messages are encoded using Base64 |
| 67 | - and transmitted as an array of such Base64 strings.</li> |
|
| 91 | + and transmitted as an array of such Base64 strings. |
|
| 92 | + </li> |
|
| 68 | 93 | </ul> |
| 69 | 94 | <h2 class="articleSubheadline">November 2024</h2> |
| 70 | 95 | <ul class="bulletList"> |
java/target/env-default-rules.sh
| ... | ... | @@ -116,11 +116,11 @@ fi |
| 116 | 116 | if [ -n "${MANAGE2SAIL_ACCESS_TOKEN}" ]; then |
| 117 | 117 | ADDITIONAL_JAVA_ARGS="${ADDITIONAL_JAVA_ARGS} -Dmanage2sail.accesstoken=${MANAGE2SAIL_ACCESS_TOKEN}" |
| 118 | 118 | fi |
| 119 | -if [ -n "${IGTIMI_CLIENT_ID}" ]; then |
|
| 120 | - ADDITIONAL_JAVA_ARGS="${ADDITIONAL_JAVA_ARGS} -Digtimi.client.id=${IGTIMI_CLIENT_ID}" |
|
| 119 | +if [ -n "${IGTIMI_BASE_URL}" ]; then |
|
| 120 | + ADDITIONAL_JAVA_ARGS="${ADDITIONAL_JAVA_ARGS} -Digtimi.base.url=${IGTIMI_BASE_URL}" |
|
| 121 | 121 | fi |
| 122 | -if [ -n "${IGTIMI_CLIENT_SECRET}" ]; then |
|
| 123 | - ADDITIONAL_JAVA_ARGS="${ADDITIONAL_JAVA_ARGS} -Digtimi.client.secret=${IGTIMI_CLIENT_SECRET}" |
|
| 122 | +if [ -n "${IGTIMI_BEARER_TOKEN}" ]; then |
|
| 123 | + ADDITIONAL_JAVA_ARGS="${ADDITIONAL_JAVA_ARGS} -Digtimi.bearer.token=${IGTIMI_BEARER_TOKEN}" |
|
| 124 | 124 | fi |
| 125 | 125 | if [ -n "${GOOGLE_MAPS_AUTHENTICATION_PARAMS}" ]; then |
| 126 | 126 | ADDITIONAL_JAVA_ARGS="${ADDITIONAL_JAVA_ARGS} -Dgoogle.maps.authenticationparams=${GOOGLE_MAPS_AUTHENTICATION_PARAMS}" |
wiki/howto/onboarding.md
| ... | ... | @@ -116,7 +116,6 @@ Out of the box, multiple settings in Eclipse need to be changed. Go to Window |
| 116 | 116 | - In "General ⇒ Editors ⇒ Text Editors ⇒ Quick Diff" change the reference source from 'Version on Disk' to 'A Git Revision'. If you like other colours for marking diffs change them here. (Example: Changes = Yellow, Additions = Green, Deletions = Red) |
| 117 | 117 | - If you'd like to be able to import official results from the Manage2Sail regatta management system: In Run/Debug ⇒ String Substitution add a variable ``MANAGE2SAIL_ACCESS_TOKEN``. Ask your team lead for the value of such an access token you can uses for testing. The variable is used by the "Sailing Server (No Proxy)" launch configuration. and maybe others. |
| 118 | 118 | - For Google Maps API access, the server needs to know authentication parameters. These are provided through an Eclipse variable used by various launch configurations named ``GOOGLE_MAPS_AUTHENTICATION_PARAMS``. Ask for the official SAP Google Maps API credentials, or use ``key=AIzaSyD1Se4tIkt-wglccbco3S7twaHiG20hR9E`` for a test key that works for your localhost-based tests. |
| 119 | -- If you'd like to work with the Igtimi YachtBot / WindBot API, you'll have to provide two additional Eclipse variables: ``IGTIMI_CLIENT_ID`` and ``IGTIMI_CLIENT_SECRET``. Again, ask your team lead for those official credentials or, if you have administrative permissions to our production landscape, look them up under each sailing-analytics-server instance's ``/root/secrets`` file. |
|
| 120 | 119 | - In "GWT ⇒ Errors/Warnings" set "Missing SDK" to "Ignore" |
| 121 | 120 | - In "GWT ⇒ GWT Settings ⇒ Add..." add the GWT SDK you downloaded and unpacked earlier |
| 122 | 121 | - In "Java ⇒ Build Path ⇒ Classpath Variables" create a new classpath variable called `ANDROID_HOME`. Set its value to the installation location of your Android SDK, e.g., `C:\Users\'user'\AppData\Local\Android\Sdk` or `/usr/local/android-sdk-linux`. |