mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-24 04:53:54 +00:00
added access token to QR code
Change-Id: I9fb1f44c8e21da4a30df9ce78dd75519c49a5476
This commit is contained in:
1 parent
4e72f2ff99
commit
1bc8300210
14 files changed
+139
-40
No files matched your search
+52
-14
@@ -1,37 +1,75 @@
|
||||
package com.sap.sailing.domain.common.impl;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.sap.sse.common.Util;
|
||||
import com.google.gwt.dev.util.collect.HashMap;
|
||||
|
||||
/**
|
||||
* This class is used by our backend, in GWT-client code and by the Android app. Therefore we cannot use classes like
|
||||
* {@link URLEncoder} to help us with the encoding.
|
||||
*/
|
||||
public class DeviceConfigurationQRCodeUtils {
|
||||
|
||||
public static final String fragmentKey = "identifier";
|
||||
|
||||
public static String composeQRContent(String deviceIdentifier, String apkUrl) {
|
||||
// poor man's uri fragment encoding: ' ' as '%20'
|
||||
String encodedIdentifier = deviceIdentifier.replaceAll(" ", "%20");
|
||||
return apkUrl + "#" + fragmentKey + "=" + encodedIdentifier;
|
||||
private static final Logger logger = Logger.getLogger(DeviceConfigurationQRCodeUtils.class.getName());
|
||||
public static final String deviceIdentifierKey = "identifier";
|
||||
public static final String accessTokenKey = "token";
|
||||
|
||||
public static class DeviceConfigurationDetails {
|
||||
private final String apkUrl;
|
||||
private final String deviceIdentifier;
|
||||
private final String accessToken;
|
||||
public DeviceConfigurationDetails(String apkUrl, String deviceIdentifier, String accessToken) {
|
||||
super();
|
||||
this.apkUrl = apkUrl;
|
||||
this.deviceIdentifier = deviceIdentifier;
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
public String getApkUrl() {
|
||||
return apkUrl;
|
||||
}
|
||||
public String getDeviceIdentifier() {
|
||||
return deviceIdentifier;
|
||||
}
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
}
|
||||
|
||||
public static Util.Pair<String, String> splitQRContent(String qrCodeContent) {
|
||||
public static String composeQRContent(String deviceIdentifier, String apkUrl, String accessToken) {
|
||||
// poor man's uri fragment encoding: ' ' as '%20'
|
||||
String encodedIdentifier = deviceIdentifier.replaceAll(" ", "%20");
|
||||
return apkUrl + "#" + deviceIdentifierKey + "=" + encodedIdentifier+"?"+accessTokenKey + "=" + accessToken;
|
||||
}
|
||||
|
||||
public static DeviceConfigurationDetails splitQRContent(String qrCodeContent) {
|
||||
int fragmentIndex = qrCodeContent.lastIndexOf('#');
|
||||
if (fragmentIndex == -1 || fragmentIndex == 0 || qrCodeContent.length() == fragmentIndex + 1) {
|
||||
throw new IllegalArgumentException("There is no server or identifier.");
|
||||
}
|
||||
String deviceIdentifier = qrCodeContent.substring(fragmentIndex + 1, qrCodeContent.length());
|
||||
if (!deviceIdentifier.startsWith(fragmentKey + "=")) {
|
||||
String fragment = qrCodeContent.substring(fragmentIndex + 1, qrCodeContent.length());
|
||||
final String[] params = fragment.split("&");
|
||||
final Map<String, String> paramMap = new HashMap<>();
|
||||
for (String param : params) {
|
||||
final String[] keyValue = param.split("=");
|
||||
if (keyValue.length == 2) {
|
||||
try {
|
||||
paramMap.put(keyValue[0], URLDecoder.decode(keyValue[1], "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
logger.severe("Internal error: Unknown encoding "+e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!fragment.startsWith(deviceIdentifierKey + "=")) {
|
||||
throw new IllegalArgumentException("The identifier is malformed");
|
||||
}
|
||||
deviceIdentifier = deviceIdentifier.substring((fragmentKey + "=").length());
|
||||
deviceIdentifier = deviceIdentifier.replaceAll("%20", " ");
|
||||
fragment = fragment.substring((deviceIdentifierKey + "=").length());
|
||||
fragment = fragment.replaceAll("%20", " ");
|
||||
|
||||
String apkUrl = qrCodeContent.substring(0, fragmentIndex);
|
||||
return new Util.Pair<String, String>(deviceIdentifier, apkUrl);
|
||||
return new DeviceConfigurationDetails(apkUrl, paramMap.get(deviceIdentifierKey), paramMap.get(accessTokenKey));
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -156,7 +156,7 @@ public class AdminConsoleEntryPoint extends AbstractSailingEntryPoint implements
|
||||
|
||||
final TabLayoutPanel raceCommitteeTabPanel = panel.addVerticalTab(getStringMessages().raceCommitteeApp(), "RaceCommiteeAppPanel");
|
||||
final DeviceConfigurationUserPanel deviceConfigurationUserPanel = new DeviceConfigurationUserPanel(sailingService,
|
||||
getStringMessages(), this);
|
||||
getUserService(), getStringMessages(), this);
|
||||
panel.addToTabPanel(raceCommitteeTabPanel, new DefaultRefreshableAdminConsolePanel<DeviceConfigurationUserPanel>(deviceConfigurationUserPanel),
|
||||
getStringMessages().deviceConfiguration(), Permission.MANAGE_DEVICE_CONFIGURATION);
|
||||
|
||||
|
||||
+9
-10
@@ -14,24 +14,23 @@ import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
|
||||
public class DeviceConfigurationQRIdentifierDialog extends DialogBox {
|
||||
public static final String rcAppApkPath = "/apps/com.sap.sailing.racecommittee.app.apk";
|
||||
private static final int qrCodeSize = 320;
|
||||
private static final int qrCodeSize = 320;
|
||||
|
||||
private class DeviceConfigurationQRIdentifierWidget extends BaseQRIdentifierWidget {
|
||||
private final TextBox identifierBox;
|
||||
private StringMessages stringMessages;
|
||||
public DeviceConfigurationQRIdentifierWidget(String identifier, StringMessages stringMessages) {
|
||||
private final StringMessages stringMessages;
|
||||
private final String accessToken;
|
||||
|
||||
public DeviceConfigurationQRIdentifierWidget(String identifier, String accessToken, StringMessages stringMessages) {
|
||||
super(qrCodeSize, stringMessages);
|
||||
|
||||
this.accessToken = accessToken;
|
||||
identifierBox = new TextBox();
|
||||
identifierBox.setValue(identifier);
|
||||
identifierBox.setReadOnly(true);
|
||||
identifierBox.setVisibleLength(40);
|
||||
|
||||
|
||||
inputGrid.resize(2, 2);
|
||||
inputGrid.setWidget(1, 0, new Label("Identifier:"));
|
||||
inputGrid.setWidget(1, 1, identifierBox);
|
||||
|
||||
this.stringMessages = stringMessages;
|
||||
}
|
||||
|
||||
@@ -41,7 +40,7 @@ public class DeviceConfigurationQRIdentifierDialog extends DialogBox {
|
||||
Window.alert(stringMessages.notCapableOfGeneratingACodeForIdentifier());
|
||||
} else if (!identifierBox.getValue().isEmpty() && !serverBox.getValue().isEmpty()) {
|
||||
String apkUrl = getServerUrlWithoutFinalSlash() + rcAppApkPath;
|
||||
return DeviceConfigurationQRCodeUtils.composeQRContent(identifierBox.getValue(), apkUrl);
|
||||
return DeviceConfigurationQRCodeUtils.composeQRContent(identifierBox.getValue(), apkUrl, accessToken);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -49,8 +48,8 @@ public class DeviceConfigurationQRIdentifierDialog extends DialogBox {
|
||||
|
||||
private final DeviceConfigurationQRIdentifierWidget widget;
|
||||
|
||||
public DeviceConfigurationQRIdentifierDialog(String identifier, StringMessages stringMessages) {
|
||||
widget = new DeviceConfigurationQRIdentifierWidget(identifier, stringMessages);
|
||||
public DeviceConfigurationQRIdentifierDialog(String identifier, StringMessages stringMessages, String accessToken) {
|
||||
widget = new DeviceConfigurationQRIdentifierWidget(identifier, accessToken, stringMessages);
|
||||
Button exitButton = new Button(stringMessages.close());
|
||||
exitButton.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
|
||||
+34
-7
@@ -3,6 +3,7 @@ package com.sap.sailing.gwt.ui.adminconsole;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.DialogBox;
|
||||
import com.google.gwt.user.client.ui.Grid;
|
||||
@@ -10,12 +11,18 @@ import com.google.gwt.user.client.ui.HorizontalPanel;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sse.gwt.client.ErrorReporter;
|
||||
import com.sap.sse.gwt.client.async.MarkedAsyncCallback;
|
||||
import com.sap.sse.security.ui.client.UserService;
|
||||
import com.sap.sse.security.ui.shared.UserDTO;
|
||||
|
||||
public class DeviceConfigurationUserDetailComposite extends DeviceConfigurationDetailComposite {
|
||||
|
||||
public DeviceConfigurationUserDetailComposite(SailingServiceAsync sailingService, ErrorReporter errorReporter,
|
||||
StringMessages stringMessages, DeviceConfigurationCloneListener listener) {
|
||||
private final UserService userService;
|
||||
|
||||
public DeviceConfigurationUserDetailComposite(SailingServiceAsync sailingService, UserService userService,
|
||||
ErrorReporter errorReporter, StringMessages stringMessages, DeviceConfigurationCloneListener listener) {
|
||||
super(sailingService, errorReporter, stringMessages, listener);
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
protected void setupIdentifier(Grid grid, int gridRow) {
|
||||
@@ -24,20 +31,40 @@ public class DeviceConfigurationUserDetailComposite extends DeviceConfigurationD
|
||||
HorizontalPanel panel = new HorizontalPanel();
|
||||
panel.add(identifierBox);
|
||||
|
||||
Button qrCodeButton = new Button("QR-Sync");
|
||||
Button qrCodeButton = new Button(stringMessages.qrSync());
|
||||
qrCodeButton.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
if (identifierBox.getValue() == null || identifierBox.getValue().isEmpty()) {
|
||||
Window.alert("There is no identifier set.");
|
||||
Window.alert(stringMessages.thereIsNoIdentifierSet());
|
||||
} else {
|
||||
DialogBox dialog = new DeviceConfigurationQRIdentifierDialog(identifierBox.getValue(), stringMessages);
|
||||
dialog.show();
|
||||
dialog.center();
|
||||
UserDTO currentUser = userService.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
createAndShowDialogForAccessToken(/* accessToken */ null);
|
||||
} else {
|
||||
userService.getUserManagementService().getAccessToken(currentUser.getName(),
|
||||
new MarkedAsyncCallback<>(new AsyncCallback<String>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError(stringMessages.couldNotObtainAccessTokenForUser(caught.getMessage()), /* silentMode */ true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(String accessToken) {
|
||||
createAndShowDialogForAccessToken(accessToken);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
panel.add(qrCodeButton);
|
||||
grid.setWidget(gridRow, 1, panel);
|
||||
}
|
||||
|
||||
private void createAndShowDialogForAccessToken(String accessToken) {
|
||||
final DialogBox dialog = new DeviceConfigurationQRIdentifierDialog(identifierBox.getValue(), stringMessages, accessToken);
|
||||
dialog.show();
|
||||
dialog.center();
|
||||
}
|
||||
}
|
||||
+7
-3
@@ -8,12 +8,16 @@ import com.sap.sse.gwt.client.ErrorReporter;
|
||||
import com.sap.sse.gwt.client.dialog.DataEntryDialog;
|
||||
import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback;
|
||||
import com.sap.sse.gwt.client.dialog.DataEntryDialog.Validator;
|
||||
import com.sap.sse.security.ui.client.UserService;
|
||||
|
||||
public class DeviceConfigurationUserPanel extends DeviceConfigurationPanel {
|
||||
|
||||
public DeviceConfigurationUserPanel(SailingServiceAsync sailingService, StringMessages stringMessages,
|
||||
ErrorReporter reporter) {
|
||||
private final UserService userService;
|
||||
|
||||
public DeviceConfigurationUserPanel(SailingServiceAsync sailingService, UserService userService,
|
||||
StringMessages stringMessages, ErrorReporter reporter) {
|
||||
super(sailingService, stringMessages, reporter);
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -25,7 +29,7 @@ public class DeviceConfigurationUserPanel extends DeviceConfigurationPanel {
|
||||
@Override
|
||||
protected DeviceConfigurationDetailComposite createDetailComposite(SailingServiceAsync sailingService,
|
||||
ErrorReporter errorReporter, StringMessages stringMessages, DeviceConfigurationCloneListener cloneListener) {
|
||||
return new DeviceConfigurationUserDetailComposite(sailingService, errorReporter, stringMessages, cloneListener);
|
||||
return new DeviceConfigurationUserDetailComposite(sailingService, userService, errorReporter, stringMessages, cloneListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
@@ -1484,4 +1484,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, c
|
||||
String failedToLinkLeaderboardToLeaderboardGroup(String leaderboardName, String leaderboardGroupName);
|
||||
String defaultLocale();
|
||||
String defaultSailorsInfoLinkInfoText();
|
||||
String qrSync();
|
||||
String thereIsNoIdentifierSet();
|
||||
String couldNotObtainAccessTokenForUser(String message);
|
||||
}
|
||||
+3
@@ -1452,3 +1452,6 @@ doYouWantToLinkLeaderboardToLeaderboardGroupOfEvent=Link leaderboard {0} to a le
|
||||
failedToLinkLeaderboardToLeaderboardGroup=Failed to link leaderboard {0} to leaderboard group {1}
|
||||
defaultLocale=Default
|
||||
defaultSailorsInfoLinkInfoText=The default link is used unless a language specific overwrite exists. If no default exists, there will be no link for languages that do not explicitly have one set.
|
||||
qrSync=QR-Sync
|
||||
thereIsNoIdentifierSet=There is no identifier set.
|
||||
couldNotObtainAccessTokenForUser=Could not obtain access token for user {0}
|
||||
+3
@@ -1442,3 +1442,6 @@ doYouWantToLinkLeaderboardToLeaderboardGroupOfEvent=Ergebnisliste {0} zu einer R
|
||||
failedToLinkLeaderboardToLeaderboardGroup=Ergebnisliste {0} konnte nicht in Ranglisten-Gruppe {1} eingefügt werden
|
||||
defaultLocale=Standard
|
||||
defaultSailorsInfoLinkInfoText=Der Standardwert wird verwendet, sofern kein Sprach-abhängiger Selglerinfo-Link hinterlegt wurde. Wenn kein Standardwert angegeben ist, so erscheint kein Selgerinfo-Link bei Sprachen, welche keinen Sprach-spezifischen Link definiert haben.
|
||||
qrSync=QR-Sync
|
||||
thereIsNoIdentifierSet=Es ist noch keine Kennung gesetzt.
|
||||
couldNotObtainAccessTokenForUser=Zugangscode für Benutzer {0} konnte nicht bezogen werden
|
||||
+3
@@ -1374,3 +1374,6 @@ doYouWantToLinkLeaderboardToLeaderboardGroupOfEvent=Link leaderboard {0} to a le
|
||||
failedToLinkLeaderboardToLeaderboardGroup=Failed to link leaderboard {0} to leaderboard group {1}
|
||||
defaultLocale=Default
|
||||
defaultSailorsInfoLinkInfoText=The default link is used unless a language specific overwrite exists. If no default exists, there will be no link for languages that do not explicitly have one set.
|
||||
qrSync=QR-Sync
|
||||
thereIsNoIdentifierSet=There is no identifier set.
|
||||
couldNotObtainAccessTokenForUser=Could not obtain access token for user {0}
|
||||
+3
@@ -1389,3 +1389,6 @@ doYouWantToLinkLeaderboardToLeaderboardGroupOfEvent=Link leaderboard {0} to a le
|
||||
failedToLinkLeaderboardToLeaderboardGroup=Failed to link leaderboard {0} to leaderboard group {1}
|
||||
defaultLocale=Default
|
||||
defaultSailorsInfoLinkInfoText=The default link is used unless a language specific overwrite exists. If no default exists, there will be no link for languages that do not explicitly have one set.
|
||||
qrSync=QR-Sync
|
||||
thereIsNoIdentifierSet=There is no identifier set.
|
||||
couldNotObtainAccessTokenForUser=Could not obtain access token for user {0}
|
||||
+2
@@ -73,6 +73,8 @@ public interface UserManagementService extends RemoteService {
|
||||
*/
|
||||
String getPreference(String username, String key);
|
||||
|
||||
String getAccessToken(String username);
|
||||
|
||||
// ------------------------------------------------ OAuth Interface --------------------------------------------------------------
|
||||
|
||||
public String getAuthorizationUrl(CredentialDTO credential) throws OAuthException;
|
||||
|
||||
+8
@@ -4,6 +4,7 @@ import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.sap.sse.security.shared.DefaultRoles;
|
||||
import com.sap.sse.security.ui.oauth.client.CredentialDTO;
|
||||
import com.sap.sse.security.ui.shared.SuccessInfo;
|
||||
import com.sap.sse.security.ui.shared.UserDTO;
|
||||
@@ -51,6 +52,13 @@ public interface UserManagementServiceAsync {
|
||||
|
||||
void getPreference(String username, String key, AsyncCallback<String> callback);
|
||||
|
||||
/**
|
||||
* Obtains an access token for the user specified by {@code username}. The caller needs to
|
||||
* have role {@link DefaultRoles#ADMIN} or be authorized as the user identified by {@code username}
|
||||
* in order to be permitted to retrieve the access token.
|
||||
*/
|
||||
void getAccessToken(String username, AsyncCallback<String> markedAsyncCallback);
|
||||
|
||||
//------------------------------------------------ OAuth Interface ----------------------------------------------------------------------
|
||||
|
||||
void getAuthorizationUrl(CredentialDTO credential, AsyncCallback<String> callback);
|
||||
|
||||
+4
@@ -433,4 +433,8 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U
|
||||
return getSecurityService().getPreference(username, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessToken(String username) {
|
||||
return getSecurityService().getAccessToken(username);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user