bug5666: exchanged null references to RaceDTOs in Autoplay and fixed an assignment in RaceBoardPanel.

- added a special initialization of EssentialSecuredDTO so that permission checks on that DTO will grand always for given actions (needed for Autoplay configuration)
- clean ups
This commit is contained in:
Udo Wessels
2022-03-21 17:11:29 +01:00
parent 1cc46f3493
commit 4f1b03eac6
9 changed files with 123 additions and 49 deletions
@@ -16,25 +16,25 @@ public class PremiumRole extends RolePrototype {
private static final long serialVersionUID = 8032532973066767581L;
private static final PremiumRole INSTANCE = new PremiumRole();
private static final String MESSAGE_KEY = "premium_role";
PremiumRole() {
super("premium", ROLE_ID.toString(),
WildcardPermission.builder().withTypes(SecuredDomainType.TRACKED_RACE)
.withActions(SecuredDomainType.TrackedRaceActions.VIEWSTREAMLETS).build(),
WildcardPermission.builder().withTypes(SecuredDomainType.SIMULATOR)
.withActions(DefaultActions.READ).build(),
WildcardPermission.builder().withTypes(SecuredDomainType.TRACKED_RACE)
.withActions(SecuredDomainType.TrackedRaceActions.SIMULATOR).build(),
WildcardPermission.builder().withTypes(SecuredSecurityTypes.USER)
.withActions(SecuredSecurityTypes.UserActions.BE_PREMIUM).build(),
WildcardPermission.builder().withTypes(SecuredDomainType.LEADERBOARD)
.withActions(SecuredDomainType.LeaderboardActions.PREMIUM_LEADERBOARD_INFORMATION).build());
.withActions(SecuredDomainType.TrackedRaceActions.VIEWSTREAMLETS,
SecuredDomainType.TrackedRaceActions.SIMULATOR)
.build(),
WildcardPermission.builder().withTypes(SecuredDomainType.SIMULATOR).withActions(DefaultActions.READ)
.build(),
WildcardPermission.builder().withTypes(SecuredSecurityTypes.USER)
.withActions(SecuredSecurityTypes.UserActions.BE_PREMIUM).build(),
WildcardPermission.builder().withTypes(SecuredDomainType.LEADERBOARD)
.withActions(SecuredDomainType.LeaderboardActions.PREMIUM_LEADERBOARD_INFORMATION).build());
}
public static PremiumRole getInstance() {
return INSTANCE;
}
public static UUID getRoleId() {
return ROLE_ID;
}
@@ -2,14 +2,19 @@ package com.sap.sailing.gwt.autoplay.client.app;
import com.sap.sailing.domain.common.DetailType;
import com.sap.sailing.domain.common.dto.AbstractLeaderboardDTO;
import com.sap.sailing.domain.common.dto.RaceDTO;
import com.sap.sailing.domain.common.security.SecuredDomainType;
import com.sap.sailing.domain.common.subscription.PremiumRole;
import com.sap.sailing.gwt.autoplay.client.shared.leaderboard.LeaderboardWithZoomingPerspectiveLifecycle;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.raceboard.RaceBoardPerspectiveLifecycle;
import com.sap.sse.gwt.client.shared.components.SettingsDialogComponent;
import com.sap.sse.gwt.client.shared.perspective.AbstractPerspectiveLifecycle;
import com.sap.sse.security.shared.dto.SecuredDTO;
import com.sap.sse.security.ui.client.UserService;
import com.sap.sse.security.ui.client.premium.PaywallResolver;
import com.sap.sse.security.ui.client.subscription.SubscriptionServiceFactory;
import com.sap.sse.security.ui.shared.EssentialSecuredDTO;
/**
* This lifecycle contains the necessary child lifecycles to allow AutoPlay to create and use both, a Leaderboard for
@@ -25,11 +30,9 @@ public class AutoplayPerspectiveLifecycle extends AbstractPerspectiveLifecycle<A
PaywallResolver paywallResolver = new PaywallResolver(userService, subscriptionServiceFactory);
leaderboardLifecycle = new LeaderboardWithZoomingPerspectiveLifecycle(leaderboard, StringMessages.INSTANCE,
availableDetailTypes, paywallResolver);
// As we cannot know, if Bravo data is available later on, we will offer DetailTypes, that might be relevant
// despite not having data for them yet
raceboardLifecycle = new RaceBoardPerspectiveLifecycle(leaderboard, StringMessages.INSTANCE,
DetailType.getAutoplayDetailTypesForChart(), userService,
paywallResolver, availableDetailTypes, null);
paywallResolver, availableDetailTypes, getEssentialRaceDTOWithPremiumActionACLs());
addLifeCycle(leaderboardLifecycle);
addLifeCycle(raceboardLifecycle);
}
@@ -38,13 +41,24 @@ public class AutoplayPerspectiveLifecycle extends AbstractPerspectiveLifecycle<A
PaywallResolver paywallResolver, Iterable<DetailType> availableDetailTypes) {
leaderboardLifecycle = new LeaderboardWithZoomingPerspectiveLifecycle(leaderboard, StringMessages.INSTANCE,
availableDetailTypes, paywallResolver);
// As we cannot know, if Bravo data is available later on, we will offer DetailTypes, that might be relevant
// despite not having data for them yet
raceboardLifecycle = new RaceBoardPerspectiveLifecycle(leaderboard, StringMessages.INSTANCE,
DetailType.getAutoplayDetailTypesForChart(), userService, paywallResolver, availableDetailTypes, null);
DetailType.getAutoplayDetailTypesForChart(), userService, paywallResolver, availableDetailTypes, getEssentialRaceDTOWithPremiumActionACLs());
addLifeCycle(leaderboardLifecycle);
addLifeCycle(raceboardLifecycle);
}
/**
* Creates a dummy race DTO with security accepting all premium actions which are based on RaceDTO type
* {@link SecuredDomainType}.TRACKED_RACE. In this case it is used to enable all features based on a raceDTO because
* the specific raceDTO is not available now. The autoplay view later will check against a real raceDTO.
*
* @return a secured DTO based on the {@link EssentialSecuredDTO} but with ACL granting race premium functions
* regardless user group participation.
*/
private SecuredDTO getEssentialRaceDTOWithPremiumActionACLs() {
return EssentialSecuredDTO.getInstanceByPermissionTypeFromPermissionSet(RaceDTO.getPermissionTypeForClass(),
PremiumRole.getInstance().getPermissions());
}
@Override
public AutoplayPerspectiveOwnSettings createPerspectiveOwnDefaultSettings() {
@@ -5,6 +5,7 @@ import java.util.Date;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.google.gwt.core.client.GWT;
@@ -43,6 +44,7 @@ import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
import com.sap.sse.gwt.client.player.Timer;
import com.sap.sse.gwt.client.player.Timer.PlayModes;
import com.sap.sse.security.shared.dto.SecuredDTO;
import com.sap.sse.security.ui.client.UserService;
import com.sap.sse.security.ui.client.premium.PaywallResolver;
import com.sap.sse.security.ui.client.subscription.SubscriptionServiceFactory;
@@ -292,26 +294,40 @@ public class AutoplayHelper {
RaceMapSettings.getDefaultManeuvers(), false, false, /* startCountDownFontSizeScaling */ 1.5,
/* showManeuverLossVisualization */ false, /* showSatelliteLayer */ false);
final PaywallResolver paywallResolver = new PaywallResolver(userService, subscriptionServiceFactory);
// TODO: set RaceDTO to RaceMapLifecycle to enable premium functions
RaceMapLifecycle raceMapLifecycle = new RaceMapLifecycle(StringMessages.INSTANCE, paywallResolver, null);
final CompetitorColorProvider colorProvider = new CompetitorColorProviderImpl(currentLiveRace, competitorsAndTheirBoats);
RaceCompetitorSelectionModel competitorSelectionProvider = new RaceCompetitorSelectionModel(
/* hasMultiSelection */ true, colorProvider, competitorsAndTheirBoats);
for (Entry<CompetitorDTO, BoatDTO> entry : competitorsAndTheirBoats.entrySet()) {
competitorSelectionProvider.setBoat(entry.getKey(), entry.getValue());
}
competitorSelectionProvider.setCompetitors(competitors);
RaceMap raceboardPerspective = new RaceMap(null, null, raceMapLifecycle, settings, sailingService,
asyncActionsExecutor, errorReporter, raceboardTimer, competitorSelectionProvider,
new RaceCompetitorSet(competitorSelectionProvider), StringMessages.INSTANCE, currentLiveRace,
raceMapResources, false, provider, paywallResolver, /* isSimulationEnabled */false);
raceboardPerspective.raceTimesInfosReceived(raceTimesInfos, clientTimeWhenRequestWasSent,
serverTimeDuringRequest, clientTimeWhenResponseWasReceived);
raceboardTimer.setPlayMode(PlayModes.Live);
// wait for one update
raceboardPerspective.onResize();
callback.onSuccess(
new RVWrapper(raceboardPerspective, competitorSelectionProvider, raceboardTimer, creationTimeProvider));
userService.createEssentialSecuredDTOByIdAndType(currentLiveRace.getPermissionType(), currentLiveRace.getName(),
currentLiveRace.getTypeRelativeObjectIdentifier(), new AsyncCallback<SecuredDTO>() {
@Override
public void onSuccess(SecuredDTO raceDtoProxy) {
RaceMapLifecycle raceMapLifecycle = new RaceMapLifecycle(StringMessages.INSTANCE,
paywallResolver, raceDtoProxy);
final CompetitorColorProvider colorProvider = new CompetitorColorProviderImpl(currentLiveRace,
competitorsAndTheirBoats);
RaceCompetitorSelectionModel competitorSelectionProvider = new RaceCompetitorSelectionModel(
/* hasMultiSelection */ true, colorProvider, competitorsAndTheirBoats);
for (Entry<CompetitorDTO, BoatDTO> entry : competitorsAndTheirBoats.entrySet()) {
competitorSelectionProvider.setBoat(entry.getKey(), entry.getValue());
}
competitorSelectionProvider.setCompetitors(competitors);
RaceMap raceboardPerspective = new RaceMap(null, null, raceMapLifecycle, settings,
sailingService, asyncActionsExecutor, errorReporter, raceboardTimer,
competitorSelectionProvider, new RaceCompetitorSet(competitorSelectionProvider),
StringMessages.INSTANCE, currentLiveRace, raceMapResources, false, provider,
paywallResolver, /* isSimulationEnabled */false);
raceboardPerspective.raceTimesInfosReceived(raceTimesInfos, clientTimeWhenRequestWasSent,
serverTimeDuringRequest, clientTimeWhenResponseWasReceived);
raceboardTimer.setPlayMode(PlayModes.Live);
// wait for one update
raceboardPerspective.onResize();
callback.onSuccess(new RVWrapper(raceboardPerspective, competitorSelectionProvider,
raceboardTimer, creationTimeProvider));
}
@Override
public void onFailure(Throwable caught) {
LOGGER.log(Level.SEVERE, "Cannot create essential raceDTO", caught);
}
});
}
}
@@ -1,7 +1,7 @@
package com.sap.sailing.gwt.ui.client;
import com.sap.sailing.gwt.ui.shared.RaceWithCompetitorsAndBoatsDTO;
import com.sap.sse.gwt.client.shared.components.ComponentLifecycle;
import com.sap.sse.security.shared.dto.SecuredDTO;
import com.sap.sse.security.ui.client.UserService;
public class RaceTimePanelLifecycle implements
@@ -11,10 +11,10 @@ public class RaceTimePanelLifecycle implements
public static final String ID = "rt";
private final RaceWithCompetitorsAndBoatsDTO raceDTO;
private final SecuredDTO raceDTO;
public RaceTimePanelLifecycle(StringMessages stringMessages, UserService userService,
final RaceWithCompetitorsAndBoatsDTO raceDTO) {
final SecuredDTO raceDTO) {
this.stringMessages = stringMessages;
this.userService = userService;
this.raceDTO = raceDTO;
@@ -1,12 +1,12 @@
package com.sap.sailing.gwt.ui.client;
import com.sap.sailing.gwt.ui.shared.RaceWithCompetitorsAndBoatsDTO;
import com.sap.sse.security.shared.dto.SecuredDTO;
import com.sap.sse.security.ui.client.UserService;
public class RaceTimePanelSettingsDialogComponent extends TimePanelSettingsDialogComponent<RaceTimePanelSettings> {
public RaceTimePanelSettingsDialogComponent(RaceTimePanelSettings settings, StringMessages stringMessages,
UserService userService, final RaceWithCompetitorsAndBoatsDTO raceDTO) {
UserService userService, final SecuredDTO raceDTO) {
super(settings, stringMessages, userService, raceDTO);
}
@@ -292,14 +292,14 @@ public class RaceBoardPanel
final CompetitorColorProvider colorProvider = new CompetitorColorProviderImpl(selectedRaceIdentifier, competitorsAndTheirBoats);
competitorSelectionProvider = new RaceCompetitorSelectionModel(/* hasMultiSelection */ true, colorProvider, competitorsAndTheirBoats);
raceMapResources.raceMapStyle().ensureInjected();
RaceMapLifecycle raceMapLifecycle = lifecycle.getRaceMapLifecycle();
final PaywallResolver paywallResolverRace = new PaywallResolver(withSecurity.getUserService(), withSecurity.getSubscriptionServiceFactory());
RaceMapLifecycle raceMapLifecycle = new RaceMapLifecycle(stringMessages, paywallResolverRace, raceDTO);
RaceMapSettings defaultRaceMapSettings = settings.findSettingsByComponentId(raceMapLifecycle.getComponentId());
RaceTimePanelLifecycle raceTimePanelLifecycle = lifecycle.getRaceTimePanelLifecycle();
RaceTimePanelSettings raceTimePanelSettings = settings
.findSettingsByComponentId(raceTimePanelLifecycle.getComponentId());
final RaceCompetitorSet raceCompetitorSet = new RaceCompetitorSet(competitorSelectionProvider);
quickFlagDataProvider = new QuickFlagDataFromLeaderboardDTOProvider(raceCompetitorSet, selectedRaceIdentifier);
final PaywallResolver paywallResolverRace = new PaywallResolver(withSecurity.getUserService(), withSecurity.getSubscriptionServiceFactory());
raceMap = new RaceMap(this, componentContext, raceMapLifecycle, defaultRaceMapSettings, sailingService, asyncActionsExecutor,
errorReporter, timer,
competitorSelectionProvider, raceCompetitorSet, stringMessages, selectedRaceIdentifier,
@@ -10,9 +10,9 @@ import com.sap.sailing.gwt.ui.client.shared.charts.MultiCompetitorRaceChartLifec
import com.sap.sailing.gwt.ui.client.shared.charts.WindChartLifecycle;
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapLifecycle;
import com.sap.sailing.gwt.ui.client.shared.racemap.maneuver.ManeuverTableLifecycle;
import com.sap.sailing.gwt.ui.shared.RaceWithCompetitorsAndBoatsDTO;
import com.sap.sse.gwt.client.shared.components.SettingsDialogComponent;
import com.sap.sse.gwt.client.shared.perspective.AbstractPerspectiveLifecycle;
import com.sap.sse.security.shared.dto.SecuredDTO;
import com.sap.sse.security.ui.client.UserService;
import com.sap.sse.security.ui.client.premium.PaywallResolver;
@@ -32,7 +32,7 @@ public class RaceBoardPerspectiveLifecycle extends AbstractPerspectiveLifecycle<
public RaceBoardPerspectiveLifecycle(AbstractLeaderboardDTO leaderboard, StringMessages stringMessages,
Iterable<DetailType> competitorChartAllowedDetailTypes, UserService userService, PaywallResolver paywallResolver,
Iterable<DetailType> availableDetailTypes, final RaceWithCompetitorsAndBoatsDTO raceDTO) {
Iterable<DetailType> availableDetailTypes, final SecuredDTO raceDTO) {
this.stringMessages = stringMessages;
raceMapLifecycle = new RaceMapLifecycle(stringMessages, paywallResolver, raceDTO);
windChartLifecycle = new WindChartLifecycle(stringMessages);
@@ -9,7 +9,6 @@ import java.util.Set;
import java.util.function.Consumer;
import java.util.logging.Logger;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.sap.sse.security.shared.HasPermissions.Action;
@@ -58,7 +57,6 @@ public class PaywallResolver {
public boolean hasPermission(final Action action, final SecuredDTO dtoContext) {
boolean hasPermission = userService.hasPermission(dtoContext, action);
GWT.log("**** hasPermission: " + hasPermission + ", action: " + action + ", context: " + dtoContext);
return hasPermission;
}
@@ -75,7 +73,6 @@ public class PaywallResolver {
public Map<Action, Boolean> getHasPermissionMap(final Set<Action> premiumActions, final SecuredDTO dtoContext) {
final Map<Action, Boolean> premiumPermissions = new HashMap<>();
for (Action premiumAction : premiumActions) {
GWT.log("### getHasPermissionMap premiumActions: " + premiumActions + ", " + dtoContext);
premiumPermissions.put(premiumAction, this.hasPermission(premiumAction, dtoContext));
}
return premiumPermissions;
@@ -1,13 +1,22 @@
package com.sap.sse.security.ui.shared;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.CustomFieldSerializer;
import com.google.gwt.user.client.rpc.IsSerializable;
import com.sap.sse.security.SecurityService;
import com.sap.sse.security.shared.HasPermissions;
import com.sap.sse.security.shared.QualifiedObjectIdentifier;
import com.sap.sse.security.shared.TypeRelativeObjectIdentifier;
import com.sap.sse.security.shared.WildcardPermission;
import com.sap.sse.security.shared.dto.AccessControlListDTO;
import com.sap.sse.security.shared.dto.SecuredDTO;
import com.sap.sse.security.shared.dto.SecurityInformationDTO;
import com.sap.sse.security.shared.dto.StrippedUserGroupDTO;
import com.sap.sse.security.ui.client.UserManagementService;
/**
@@ -62,4 +71,42 @@ public class EssentialSecuredDTO extends SecurityInformationDTO implements Secur
return name;
}
/**
* Creates an {@link EssentialSecuredDTO} with the defined permissionType and all actions from given permission set.
*
* @param permissionType
* the permission type of the new DTO
* @param wildcardPermissions
* a set of {@link WildcardPermission}s including actions. Only actions set to given permission type will
* be used
* @return a new essential security DTO without data, name or identifier. Only a ACL will be added including all
* actions from wildcarPermissions matching given permission type. This ACL will be valid regardless any
* user group participation ({@code null} key).
*/
public static EssentialSecuredDTO getInstanceByPermissionTypeFromPermissionSet(HasPermissions permissionType,
Set<WildcardPermission> wildcardPermissions) {
EssentialSecuredDTO essentialSecuredDTO = new EssentialSecuredDTO(permissionType, /* name */ null,
new TypeRelativeObjectIdentifier());
// create an ACL for all actions from given domain type
final Map<StrippedUserGroupDTO, Set<String>> permissionMap = new HashMap<>();
final Set<String> wildcardsAsStringSet = new HashSet<>();
// collect all actions
for (WildcardPermission permission : wildcardPermissions) {
final Set<String> domains = permission.getParts().get(0);
// Only get actions which are valid for given domain type
GWT.log("** domains: " + domains);
if (domains.contains(permissionType.getName())) {
final Set<String> actions = permission.getParts().get(1);
GWT.log("** actions: " + actions);
wildcardsAsStringSet.addAll(actions);
}
}
GWT.log("********** wildcardPermissions: " + wildcardsAsStringSet);
// put all collected actions to default permission (null) entry.
permissionMap.put(null, wildcardsAsStringSet);
AccessControlListDTO accessControlListDTO = new AccessControlListDTO(permissionMap);
essentialSecuredDTO.setAccessControlList(accessControlListDTO);
return essentialSecuredDTO;
}
}