Merge branch 'master' into bug5085

This commit is contained in:
Steffen Schaefer committed 2020-01-13 15:03:02 +01:00
commit 93bbc8e83c
15 files changed
+69 -54

No files matched your search

@@ -1,14 +1,17 @@
package com.sap.sailing.domain.common;
public class BranchIOConstants {
public static final String SAILINSIGHT_2_APP_BRANCHIO = "https://sailinsight20-app.sapsailing.com/invite";
public static final String SAILINSIGHT_APP_BRANCHIO = "https://sailinsight-app.sapsailing.com/invite";
public static final String SAILINSIGHT_2_APP_BRANCHIO = "https://sailinsight20-app.sapsailing.com/invite";
public static final String SAILINSIGHT_3_APP_BRANCHIO = "https://sailinsight30-app.sapsailing.com/invite";
public static final String SAILINSIGHT_APP_BRANCHIO_PATH = "checkinUrl";
public static final String BUOYPINGER_APP_BRANCHIO = "https://buoypinger-app.sapsailing.com/invite";
public static final String BUOYPINGER_APP_BRANCHIO_PATH = "checkinUrl";
public static final String OPEN_REGATTA_2_APP_BRANCHIO = "https://sailinsight20-app.sapsailing.com/publicInvite";
public static final String OPEN_REGATTA_2_APP_BRANCHIO_PATH = "checkinUrl";
public static final String OPEN_REGATTA_3_APP_BRANCHIO = "https://sailinsight30-app.sapsailing.com/publicInvite";
public static final String OPEN_REGATTA_3_APP_BRANCHIO_PATH = "checkinUrl";
private BranchIOConstants() {
};
}
}
@@ -3,7 +3,8 @@ package com.sap.sailing.domain.common;
public enum MailInvitationType {
LEGACY,
SailInsight1,
SailInsight2;
SailInsight2,
SailInsight3;
public static final String SYSTEM_PROPERTY_NAME = "com.sap.sailing.domain.tracking.MailInvitationType";
}
@@ -5,7 +5,6 @@ import java.util.Locale;
import com.sap.sailing.domain.common.BranchIOConstants;
public class BranchIO2RaceLogTrackingInvitationMailBuilder extends BranchIORaceLogTrackingInvitationMailBuilder {
BranchIO2RaceLogTrackingInvitationMailBuilder(Locale locale) {
super(locale);
}
@@ -20,5 +19,4 @@ public class BranchIO2RaceLogTrackingInvitationMailBuilder extends BranchIORaceL
// FIXME the app should in the future at some point also support bouy pinging, replace this then
return BranchIOConstants.BUOYPINGER_APP_BRANCHIO;
}
}
@@ -0,0 +1,24 @@
package com.sap.sailing.domain.racelogtracking.impl;
import java.util.Locale;
import com.sap.sailing.domain.common.BranchIOConstants;
public class BranchIO3RaceLogTrackingInvitationMailBuilder extends BranchIORaceLogTrackingInvitationMailBuilder {
BranchIO3RaceLogTrackingInvitationMailBuilder(Locale locale) {
super(locale);
}
@Override
protected String getSailInsightBranchIO() {
return BranchIOConstants.SAILINSIGHT_3_APP_BRANCHIO;
}
@Override
protected String getBouyPingerBranchIO() {
// FIXME the app should in the future at some point also support bouy pinging, replace this then
return BranchIOConstants.BUOYPINGER_APP_BRANCHIO;
}
}
@@ -359,6 +359,9 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
case SailInsight2:
mail = new BranchIO2RaceLogTrackingInvitationMailBuilder(locale);
break;
case SailInsight3:
mail = new BranchIO3RaceLogTrackingInvitationMailBuilder(locale);
break;
default:
throw new IllegalArgumentException("Unhandled mail type");
}
@@ -330,7 +330,7 @@ public class ORCPublicCertificateDatabaseImpl implements ORCPublicCertificateDat
builder = child.getTextContent();
break;
case "dxtDate":
issueDate = new MillisecondsTimePoint(isoTimestampFormat.parse(child.getTextContent()+"+0000")); // assume UTC
issueDate = new MillisecondsTimePoint(isoTimestampFormat.parse(child.getTextContent().replaceAll("Z", "+0000"))); // assume UTC
break;
case "CertType":
certType = Integer.valueOf(child.getTextContent().trim());
@@ -166,6 +166,7 @@ public class QRCodePlace extends AbstractBasePlace {
}
public String getPublicInviteBranchIOUrl() {
// TODO why is this specific to version 2 and not considering the default server setting for mailInvitationType?
return BranchIOConstants.OPEN_REGATTA_2_APP_BRANCHIO + "?" + QRCodePlace.PARAM_REGATTA_NAME + "="
+ encodeUrl(publicRegattaName) + "&" + QRCodePlace.PARAM_REGATTA_SECRET + "="
+ encodeUrl(regattaRegistrationLinkSecret) + "&" + QRCodePlace.PARAM_SERVER + "="
@@ -144,12 +144,9 @@ public class RegattaDetailsComposite extends Composite {
Button button = new Button(stringMessages.registrationLinkShare(), new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
RegistrationLinkWithQRCode registrationLinkWithQRCode = new RegistrationLinkWithQRCode();
registrationLinkWithQRCode.setSecret(regatta.registrationLinkSecret);
sailingService.getMailType(new AsyncCallback<MailInvitationType>() {
@Override
public void onFailure(Throwable caught) {
logger.log(Level.SEVERE, "Could not determine MailInvitationType", caught);
@@ -221,21 +221,28 @@ public class RegattaLogAddDeviceMappingDialog extends DataEntryDialogWithDateTim
String url = DeviceMappingConstants.getDeviceMappingForRegattaLogUrl(baseUrlWithoutTrailingSlash,
eventIdAsString, leaderboardName, mappedItemType, mappedItemId, regattaRegisterSecret,
GwtUrlHelper.INSTANCE);
if (mailInvitationType == MailInvitationType.LEGACY) {
switch (mailInvitationType) {
case LEGACY:
// URL is already legacy
} else if (mailInvitationType == MailInvitationType.SailInsight1) {
break;
case SailInsight1:
url = BranchIOConstants.SAILINSIGHT_APP_BRANCHIO + "?"
+ BranchIOConstants.SAILINSIGHT_APP_BRANCHIO_PATH + "="
+ GwtUrlHelper.INSTANCE.encodeQueryString(url);
} else if (mailInvitationType == MailInvitationType.SailInsight2) {
break;
case SailInsight2:
url = BranchIOConstants.SAILINSIGHT_2_APP_BRANCHIO + "?"
+ BranchIOConstants.OPEN_REGATTA_2_APP_BRANCHIO_PATH + "="
+ GwtUrlHelper.INSTANCE.encodeQueryString(url);
}
else {
break;
case SailInsight3:
url = BranchIOConstants.SAILINSIGHT_3_APP_BRANCHIO + "?"
+ BranchIOConstants.OPEN_REGATTA_3_APP_BRANCHIO_PATH + "="
+ GwtUrlHelper.INSTANCE.encodeQueryString(url);
break;
default:
throw new QRCodeURLCreationException("Unknown mail invitation type: " + mailInvitationType);
}
return url;
}
});
@@ -63,14 +63,10 @@ public class RegistrationLinkWithQRCodeDialog extends DataEntryDialog<Registrati
this.invitationType = invitationType;
this.registrationLinkWithQRCode = registrationLinkWithQRCode == null ? new RegistrationLinkWithQRCode()
: registrationLinkWithQRCode;
registrationLinkPanel = new CaptionPanel(stringMessages.registrationLinkUrl());
registrationLinkPanelContent = new VerticalPanel();
registrationLinkPanel.add(registrationLinkPanelContent);
final Label eventExplain = new Label(stringMessages.event());
events = createGenericListBox(new ValueBuilder<EventDTO>() {
@Override
public String getValue(EventDTO item) {
@@ -98,10 +94,8 @@ public class RegistrationLinkWithQRCodeDialog extends DataEntryDialog<Registrati
updateDisplayWidgets();
}
});
registrationLinkPanelContent.add(eventExplain);
registrationLinkPanelContent.add(events);
registrationLinkExplain = new Label(stringMessages.registrationLinkUrlExplain());
registrationLinkPanelContent.add(registrationLinkExplain);
urlTextBox = createTextBox("URL", 100);
@@ -109,7 +103,6 @@ public class RegistrationLinkWithQRCodeDialog extends DataEntryDialog<Registrati
registrationLinkPanelContent.add(urlTextBox);
Anchor copyAnchor = new Anchor(stringMessages.registrationLinkUrlCopy());
copyAnchor.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
urlTextBox.setFocus(true);
@@ -118,7 +111,6 @@ public class RegistrationLinkWithQRCodeDialog extends DataEntryDialog<Registrati
}
});
registrationLinkPanelContent.add(copyAnchor);
barcodePanel = new CaptionPanel(stringMessages.registrationLinkDialogQrcode());
barcodePanelContent = new VerticalPanel();
barcodePanel.add(barcodePanelContent);
@@ -144,7 +136,6 @@ public class RegistrationLinkWithQRCodeDialog extends DataEntryDialog<Registrati
}
final VerticalPanel dialogPanel = new VerticalPanel();
panel.add(dialogPanel);
dialogPanel.add(registrationLinkPanel);
dialogPanel.add(barcodePanel);
return panel;
@@ -155,29 +146,27 @@ public class RegistrationLinkWithQRCodeDialog extends DataEntryDialog<Registrati
Notification.notify(stringMessages.noEventSelected(), NotificationType.ERROR);
return;
}
String baseUrl = GWT.getHostPageBaseURL();
if (baseUrl.endsWith("/")) {
baseUrl = baseUrl.substring(0, baseUrl.lastIndexOf("/"));
baseUrl = baseUrl.substring(0, baseUrl.indexOf("/gwt"));
}
final String eventIdAsString = events.getValue().id.toString();
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("regatta_name", regattaName);
parameters.put("secret", secret);
parameters.put("server", baseUrl);
parameters.put("event_id", eventIdAsString);
// TODO decide OPEN_REGATTA link variant based on invitationType
String deeplinkUrl = BranchIO.generateLink(BranchIOConstants.OPEN_REGATTA_2_APP_BRANCHIO, parameters,
URL::encodeQueryString);
urlTextBox.setText(deeplinkUrl);
if (invitationType != MailInvitationType.SailInsight2) {
if (invitationType != MailInvitationType.SailInsight2 &&
invitationType != MailInvitationType.SailInsight3) { // TODO it would be better to make it a property of an enum literal whether open regatta invitation is possible
getStatusLabel().setText(stringMessages.warningSailInsightVersion());
getStatusLabel().setStyleName("errorLabel");
}
sailingService.openRegattaRegistrationQrCode(deeplinkUrl, new AsyncCallback<String>() {
@Override
public void onFailure(Throwable caught) {
GWT.log("Qrcode generation failed: ", caught);
@@ -187,9 +176,7 @@ public class RegistrationLinkWithQRCodeDialog extends DataEntryDialog<Registrati
public void onSuccess(String result) {
GWT.log("Qrcode generated for url: " + deeplinkUrl);
qrCodeImage.setUrl("data:image/png;base64, " + result);
}
});
}
@@ -40,7 +40,7 @@
-->
<system-property>
<name>webdriver.chrome.driver</name>
<value>C:\apps\ChromeSeleniumDriver\chromedriver.exe</value>
<value>/usr/bin/chromedriver</value>
</system-property>
<!--
You need geckodriver to be able to run Selenium tests on Firefox.
@@ -50,7 +50,7 @@
-->
<system-property>
<name>webdriver.gecko.driver</name>
<value>/path/to/geckodriver.exe</value>
<value>/usr/bin/geckodriver</value>
</system-property>
<!--
geckodriver automatically finds an installed version of Firefox.
@@ -86,12 +86,14 @@
The capabilities section can be used for fine tuning of the driver (e.g. version). For more informations see the
pages mentioned above.
-->
<!--
<!-- -->
<driver-definition class="org.openqa.selenium.firefox.FirefoxDriver">
</driver-definition>
-->
<!-- -->
<!--
<driver-definition class="org.openqa.selenium.chrome.ChromeDriver">
</driver-definition>
-->
<!--
<driver-definition class="org.openqa.selenium.ie.InternetExplorerDriver">
<capabilities>
@@ -191,7 +191,6 @@ public class RegattaApiTest extends AbstractSeleniumTest {
public void testRegisterExistingCompetitorWithSecret() {
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");
@@ -200,22 +199,17 @@ public class RegattaApiTest extends AbstractSeleniumTest {
ApiContext.SECURITY_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");
// ensure the reader can actually see the competitor
UserGroup group = usergroupApi.getUserGroupByName(userWithCompetitorAndSecurityCtx, "donald"+SecurityService.TENANT_SUFFIX);
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()));
Competitor[] competitors = regattaApi.getCompetitors(userOwningEventCtx, OTHER_EVENT_NAME);
assertEquals(1, competitors.length);
assertEquals(competitor.getId(), competitors[0].getId());
}
@@ -140,7 +140,6 @@ public class Activator implements BundleActivator {
waitForUserStoreService(bundleContext);
}
context.registerService(ClearStateTestSupport.class, new ClearStateTestSupport() {
@Override
public void clearState() throws Exception {
Activator.this.clearState();
@@ -149,7 +148,7 @@ public class Activator implements BundleActivator {
}
/**
* This method will clean the userStore and AccessControllStore, and reset the securityService. It will then
* This method will clean the userStore and AccessControlStore, and reset the securityService. It will then
* reinitialize them in the same fashion an empty server will do.
*/
protected void clearState() throws InterruptedException, UserGroupManagementException, UserManagementException {
@@ -268,19 +268,17 @@ public class UserGroupResource extends AbstractSecurityResource {
public Response addRoleToUserGroup(@PathParam(KEY_GROUP_ID) String userGroupId,
@PathParam(KEY_ROLE_ID) String roleIdString, String body) {
Response response;
try {
final UUID groupId = UUID.fromString(userGroupId);
final UserGroup usergroup = getService().getUserGroup(groupId);
final UUID roleId = UUID.fromString(roleIdString);
final UserGroup usergroup = getService().getUserGroup(groupId);
if (usergroup == null) {
response = Response.status(Status.BAD_REQUEST).entity("Usergroup with this name does not exist.")
.build();
response = Response.status(Status.BAD_REQUEST).entity(
String.format("Usergroup with ID %s does not exist.", userGroupId)).build();
} else {
final RoleDefinition role = getService().getRoleDefinition(roleId);
if (role == null) {
response = Response.status(Status.BAD_REQUEST).entity("Role with this id does not exist.").build();
response = Response.status(Status.BAD_REQUEST).entity(String.format("Role with ID %s does not exist.", roleId)).build();
} else {
if (getService().hasCurrentUserUpdatePermission(usergroup)
&& getService().hasCurrentUserReadPermission(role)) {
@@ -291,15 +289,16 @@ public class UserGroupResource extends AbstractSecurityResource {
if (!getService().hasCurrentUserMetaPermissionsOfRoleDefinitionWithQualification(role,
new Ownership(null, usergroup))) {
response = Response.status(Status.UNAUTHORIZED)
.entity(String.format("Not permitted to add role %s to group", role.getName()))
.build();
.entity(String.format("Not permitted to add role %s to group %s",
role.getName(), usergroup.getName())).build();
} else {
getService().putRoleDefinitionToUserGroup(usergroup, role, roleForAll);
response = Response.ok().build();
}
} else {
response = Response.status(Status.BAD_REQUEST)
.entity("Role was already added to the group.").build();
.entity(String.format("Role %s was already added to group %s.", role.getName(),
usergroup.getName())).build();
}
} else {
response = Response.status(Status.UNAUTHORIZED).build();
@@ -113,7 +113,7 @@
</tr>
</table>
<br/>
<b>Delete a user from a UserGroup</b>
<b>Delete a user from a UserGroup</b>
<table>
<tr>
<td>Request Method:</td>
@@ -156,7 +156,7 @@
</tr>
<tr>
<td>Example:</td>
<td><code>curl -X PUT -d '{"roleAssociated": true}' "127.0.0.1:8888/security/api/restsecurity/usergroup/9201d7cb-969e-4975-8cf1-32972bb2c8ba/role/29914406-b0fc-43cd-acc7-62a83931f587"</code><br></td>
<td><code>curl -X PUT -d '{"forAll": true}' "127.0.0.1:8888/security/api/restsecurity/usergroup/9201d7cb-969e-4975-8cf1-32972bb2c8ba/role/29914406-b0fc-43cd-acc7-62a83931f587"</code><br></td>
</tr>
</table>
<br/>