From 6196629a80d7cf9165aac98d64464dccf853241d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20B=C3=B6rnert?= Date: Thu, 7 Mar 2019 15:33:43 +0100 Subject: [PATCH 01/26] return 404 if invalid entities are requested, instead of failing their securitycheck first --- .../jaxrs/api/CompetitorsResource.java | 10 +- .../jaxrs/api/LeaderboardsResource.java | 14 ++- .../gateway/jaxrs/api/MarkRessource.java | 94 +++++++++++-------- .../gateway/jaxrs/api/WindResource.java | 4 +- 4 files changed, 75 insertions(+), 47 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java index 83b40b5f716..3b24f4844de 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java @@ -77,11 +77,12 @@ public class CompetitorsResource extends AbstractSailingServerResource { public Response getCompetitor(@PathParam("competitorId") String competitorIdAsString, @QueryParam("secret") String secret, @QueryParam("leaderboardname") String leaderboardName) { Response response; - Competitor competitor = getService().getCompetitorAndBoatStore().getExistingCompetitorByIdAsString( - competitorIdAsString); + Competitor competitor = getService().getCompetitorAndBoatStore() + .getExistingCompetitorByIdAsString(competitorIdAsString); if (competitor == null) { response = Response.status(Status.NOT_FOUND) - .entity("Could not find a competitor with id '" + StringEscapeUtils.escapeHtml(competitorIdAsString) + "'.") + .entity("Could not find a competitor with id '" + StringEscapeUtils.escapeHtml(competitorIdAsString) + + "'.") .type(MediaType.TEXT_PLAIN).build(); } else { boolean skip = skipChecksDueToCorrectSecret(leaderboardName, secret); @@ -89,7 +90,8 @@ public class CompetitorsResource extends AbstractSailingServerResource { getSecurityService().checkCurrentUserReadPermission(competitor); } String jsonString = getCompetitorJSON(competitor).toJSONString(); - response = Response.ok(jsonString).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build(); + response = Response.ok(jsonString).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8") + .build(); } return response; } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java index 3aa05d18ad0..de45a7784e6 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java @@ -975,9 +975,17 @@ public class LeaderboardsResource extends AbstractLeaderboardsResource { @QueryParam(RaceLogServletConstants.PARAMS_RACE_COLUMN_NAME) String raceColumnName, @QueryParam(RaceLogServletConstants.PARAMS_RACE_FLEET_NAME) String fleetName) throws MalformedURLException, IOException, InterruptedException { - SecurityUtils.getSubject().checkPermission(SecuredDomainType.LEADERBOARD.getStringPermissionForObject( - DefaultActions.UPDATE, getService().getLeaderboardByName(leaderboardName))); - return stopOrRemoveTrackedRace(leaderboardName, raceColumnName, fleetName, true); + Leaderboard leaderBoard = getService().getLeaderboardByName(leaderboardName); + Response result = null; + if(leaderBoard == null) { + result = Response.status(Status.NOT_FOUND) + .entity("Could not find a leaderboard with name '" + StringEscapeUtils.escapeHtml(leaderboardName) + "'.") + .type(MediaType.TEXT_PLAIN).build(); + } else { + getSecurityService().checkCurrentUserUpdatePermission(leaderBoard); + result = stopOrRemoveTrackedRace(leaderboardName, raceColumnName, fleetName, true); + } + return result; } @POST diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/MarkRessource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/MarkRessource.java index fbd7dfecc41..be29c756b49 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/MarkRessource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/MarkRessource.java @@ -15,7 +15,9 @@ import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import org.apache.commons.lang.StringEscapeUtils; import org.apache.shiro.SecurityUtils; import org.json.simple.JSONArray; import org.json.simple.JSONObject; @@ -82,15 +84,23 @@ public class MarkRessource extends AbstractSailingServerResource { Mark mark = getService().getBaseDomainFactory().getOrCreateMark(markId, markName); String regattaName = (String) requestObject.get("regattaName"); Regatta regatta = getService().getRegattaByName(regattaName); - SecurityUtils.getSubject().checkPermission(regatta.getIdentifier().getStringPermission(DefaultActions.UPDATE)); - RegattaLog regattaLog = getRegattaLogInternal(regattaName); - RegattaLogDefineMarkEventImpl event = new RegattaLogDefineMarkEventImpl(MillisecondsTimePoint.now(), - getService().getServerAuthor(), MillisecondsTimePoint.now(), UUID.randomUUID(), mark); - regattaLog.add(event); - JSONObject answer = new JSONObject(); - answer.put("markId", markId.toString()); - return Response.ok(answer.toJSONString()).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8") - .build(); + Response response; + if (regatta == null) { + response = Response.status(Status.NOT_FOUND) + .entity("Could not find a regatta with name '" + StringEscapeUtils.escapeHtml(regattaName) + "'.") + .type(MediaType.TEXT_PLAIN).build(); + } else { + getSecurityService().checkCurrentUserUpdatePermission(regatta); + RegattaLog regattaLog = getRegattaLogInternal(regattaName); + RegattaLogDefineMarkEventImpl event = new RegattaLogDefineMarkEventImpl(MillisecondsTimePoint.now(), + getService().getServerAuthor(), MillisecondsTimePoint.now(), UUID.randomUUID(), mark); + regattaLog.add(event); + JSONObject answer = new JSONObject(); + answer.put("markId", markId.toString()); + response = Response.ok(answer.toJSONString()) + .header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build(); + } + return response; } @POST @@ -221,36 +231,46 @@ public class MarkRessource extends AbstractSailingServerResource { JSONObject requestObject = Helpers.toJSONObjectSafe(requestBody); String leaderboardName = (String) requestObject.get("leaderboardName"); - SecurityUtils.getSubject().checkPermission(SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier( - DefaultActions.UPDATE, Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); - String raceColumnName = (String) requestObject.get("raceColumnName"); - String fleetName = (String) requestObject.get("fleetName"); + Leaderboard leaderBoard = getService().getLeaderboardByName(leaderboardName); + Response response; + if (leaderBoard == null) { + response = Response.status(Status.NOT_FOUND).entity( + "Could not find a leaderboard with name '" + StringEscapeUtils.escapeHtml(leaderboardName) + "'.") + .type(MediaType.TEXT_PLAIN).build(); + } else { + SecurityUtils.getSubject().checkPermission( + SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, + Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); + String raceColumnName = (String) requestObject.get("raceColumnName"); + String fleetName = (String) requestObject.get("fleetName"); - JSONArray competitorsRaw = (JSONArray) requestObject.get("competitors"); - Map competitorsToRegister = new HashMap<>(); - for (int i = 0; i < competitorsRaw.size(); i++) { - JSONObject competitorRaw = (JSONObject) competitorsRaw.get(i); - String competitorId = (String) competitorRaw.get("competitorId"); - String boatId = (String) competitorRaw.get("boatId"); - Competitor competitor = getService().getCompetitorAndBoatStore() - .getExistingCompetitorByIdAsString(competitorId); - Boat boat = getService().getCompetitorAndBoatStore().getExistingBoatByIdAsString(boatId); - competitorsToRegister.put(competitor, boat); + JSONArray competitorsRaw = (JSONArray) requestObject.get("competitors"); + Map competitorsToRegister = new HashMap<>(); + for (int i = 0; i < competitorsRaw.size(); i++) { + JSONObject competitorRaw = (JSONObject) competitorsRaw.get(i); + String competitorId = (String) competitorRaw.get("competitorId"); + String boatId = (String) competitorRaw.get("boatId"); + Competitor competitor = getService().getCompetitorAndBoatStore() + .getExistingCompetitorByIdAsString(competitorId); + Boat boat = getService().getCompetitorAndBoatStore().getExistingBoatByIdAsString(boatId); + competitorsToRegister.put(competitor, boat); + } + RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); + Fleet fleet = getFleetByName(raceColumn, fleetName); + Map competitorsRegisteredInRaceLog = new HashMap<>(); + for (final Entry e : raceColumn.getCompetitorsRegisteredInRacelog(fleet).entrySet()) { + competitorsRegisteredInRaceLog.put((CompetitorWithBoat) e.getKey(), e.getValue()); + } + final Iterable competitorSetToRemove = filterCompetitorDuplicates(competitorsToRegister, + competitorsRegisteredInRaceLog); + raceColumn.deregisterCompetitors(competitorSetToRemove, fleet); + // we assume that the competitors id of type Competitor here, so we need to find the corresponding boat + for (Entry competitorToRegister : competitorsToRegister.entrySet()) { + raceColumn.registerCompetitor(competitorToRegister.getKey(), competitorToRegister.getValue(), fleet); + } + response = Response.ok().header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build(); } - RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); - Fleet fleet = getFleetByName(raceColumn, fleetName); - Map competitorsRegisteredInRaceLog = new HashMap<>(); - for (final Entry e : raceColumn.getCompetitorsRegisteredInRacelog(fleet).entrySet()) { - competitorsRegisteredInRaceLog.put((CompetitorWithBoat) e.getKey(), e.getValue()); - } - final Iterable competitorSetToRemove = filterCompetitorDuplicates(competitorsToRegister, - competitorsRegisteredInRaceLog); - raceColumn.deregisterCompetitors(competitorSetToRemove, fleet); - // we assume that the competitors id of type Competitor here, so we need to find the corresponding boat - for (Entry competitorToRegister : competitorsToRegister.entrySet()) { - raceColumn.registerCompetitor(competitorToRegister.getKey(), competitorToRegister.getValue(), fleet); - } - return Response.ok().header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build(); + return response; } private Iterable filterCompetitorDuplicates(Map competitorToBoatMappingsToRegister, diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/WindResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/WindResource.java index 28925cdaa7e..f59d700ec49 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/WindResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/WindResource.java @@ -6,7 +6,6 @@ import javax.ws.rs.Path; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import org.apache.shiro.SecurityUtils; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.JSONValue; @@ -24,7 +23,6 @@ import com.sap.sailing.server.gateway.deserialization.impl.Helpers; import com.sap.sailing.server.gateway.deserialization.impl.PositionJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.WindJsonDeserializer; import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource; -import com.sap.sse.security.shared.HasPermissions.DefaultActions; @Path("/v1/wind") public class WindResource extends AbstractSailingServerResource { @@ -47,7 +45,7 @@ public class WindResource extends AbstractSailingServerResource { String raceName = (String) regattaNameAndRaceNameObject.get("raceName"); RegattaNameAndRaceName identifier = new RegattaNameAndRaceName(regattaName, raceName); // add wind only to those races the subject is permitted to update - if (SecurityUtils.getSubject().isPermitted(identifier.getIdentifier().getStringPermission(DefaultActions.UPDATE))) { + if (getSecurityService().hasCurrentUserUpdatePermission(identifier)) { JSONObject answerForRace = new JSONObject(); answerForRace.put("regattaNameAndRaceName", regattaNameAndRaceName); if (windSourceType == WindSourceType.EXPEDITION || windSourceType == WindSourceType.WEB) { From f8e4f3a98a58c7b6bc0ff69390ae94af6c33e5eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20B=C3=B6rnert?= Date: Thu, 7 Mar 2019 16:12:47 +0100 Subject: [PATCH 02/26] secured export as described in bug4934 --- .../domain/common/security/SecuredDomainType.java | 12 +++++++----- .../ui/adminconsole/TrackedRacesListComposite.java | 8 +++++++- .../trackfiles/impl/TrackFilesExportPostServlet.java | 9 ++++++++- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/security/SecuredDomainType.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/security/SecuredDomainType.java index 360a855e0f2..8e882d47a46 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/security/SecuredDomainType.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/security/SecuredDomainType.java @@ -49,14 +49,16 @@ public class SecuredDomainType extends HasPermissionsImpl { TrackedRaceActions.ALL_ACTIONS); public static enum TrackedRaceActions implements Action { - CAN_REPLAY_DURING_LIVE_RACES, DETAIL_TIMER; + CAN_REPLAY_DURING_LIVE_RACES, + DETAIL_TIMER, + EXPORT; - private static final Action[] ALL_ACTIONS = new Action[] { CAN_REPLAY_DURING_LIVE_RACES, DefaultActions.READ, + private static final Action[] ALL_ACTIONS = DefaultActions.plus(CAN_REPLAY_DURING_LIVE_RACES, DETAIL_TIMER, + EXPORT); + + public static final Action[] MUTATION_ACTIONS = new Action[] { EXPORT, DefaultActions.DELETE, DefaultActions.CREATE, DefaultActions.UPDATE, DefaultActions.CHANGE_OWNERSHIP, DefaultActions.CHANGE_ACL }; - - public static final Action[] MUTATION_ACTIONS = new Action[] { DefaultActions.CREATE, DefaultActions.UPDATE, - DefaultActions.CHANGE_OWNERSHIP, DefaultActions.CHANGE_ACL }; } public static enum CompetitorAndBoatActions implements Action { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackedRacesListComposite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackedRacesListComposite.java index 6c030f4c85b..f22bc8814ca 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackedRacesListComposite.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackedRacesListComposite.java @@ -15,6 +15,7 @@ import com.google.gwt.user.client.ui.HorizontalPanel; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.RegattaNameAndRaceName; import com.sap.sailing.domain.common.dto.RaceDTO; +import com.sap.sailing.domain.common.security.SecuredDomainType; import com.sap.sailing.gwt.ui.client.RegattaRefresher; import com.sap.sailing.gwt.ui.client.RegattasDisplayer; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; @@ -184,6 +185,7 @@ public class TrackedRacesListComposite extends AbstractTrackedRacesListComposite boolean canUpdateAll = true; boolean canDeleteAll = true; + boolean canExportAll = true; for (RaceDTO race : selectedRaces) { if (!userService.hasPermission(race, DefaultActions.UPDATE)) { canUpdateAll = false; @@ -191,11 +193,15 @@ public class TrackedRacesListComposite extends AbstractTrackedRacesListComposite if (!userService.hasPermission(race, DefaultActions.DELETE)) { canDeleteAll = false; } + if (!userService.hasPermission(race, SecuredDomainType.TrackedRaceActions.EXPORT)) { + canExportAll = false; + } + } btnSetDelayToLive.setEnabled(canUpdateAll); btnRemoveRace.setEnabled(canDeleteAll); btnUntrack.setEnabled(canUpdateAll); - btnExport.setEnabled(numberOfItemsSelected > 0); + btnExport.setEnabled(canExportAll); } } } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/TrackFilesExportPostServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/TrackFilesExportPostServlet.java index 6f96b3270ef..2dcab62e67a 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/TrackFilesExportPostServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/TrackFilesExportPostServlet.java @@ -11,8 +11,11 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.shiro.SecurityUtils; + import com.sap.sailing.domain.base.RaceDefinition; import com.sap.sailing.domain.base.Regatta; +import com.sap.sailing.domain.common.security.SecuredDomainType.TrackedRaceActions; import com.sap.sailing.domain.common.trackfiles.TrackFilesDataSource; import com.sap.sailing.domain.common.trackfiles.TrackFilesExportParameters; import com.sap.sailing.domain.common.trackfiles.TrackFilesFormat; @@ -81,8 +84,12 @@ public class TrackFilesExportPostServlet extends SailingServerHttpServlet { resp.setHeader("Content-Disposition", "attachment; filename=\"tracked-races.zip\""); resp.setContentType("application/zip"); - ZipOutputStream out = new ZipOutputStream(resp.getOutputStream()); List trackedRaces = getTrackedRaces(regattaRaces); + for (TrackedRace trackedRace : trackedRaces) { + SecurityUtils.getSubject() + .checkPermission(trackedRace.getIdentifier().getStringPermission(TrackedRaceActions.EXPORT)); + } + ZipOutputStream out = new ZipOutputStream(resp.getOutputStream()); boolean beforeAfter = beforeAfterString == null ? false : true; boolean rawFixes = rawFixesString == null ? false : true; TrackFilesFormat format = TrackFilesFormat.valueOf(formatString); From e97390326e046b5374833110bb72603801ef57f8 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Thu, 7 Mar 2019 17:03:18 +0100 Subject: [PATCH 03/26] Bug 4937: moved READ_PUBLIC to SecuredSecurityType and removed CompetitorAndBoatAction accordingly. --- .../common/security/SecuredDomainType.java | 18 ++++++------------ .../user/profile/GetCompetitorAction.java | 4 ++-- .../adminconsole/AdminConsoleEntryPoint.java | 6 +++--- .../gwt/ui/server/SailingServiceImpl.java | 6 +++--- ...TrackWithEstimationDataJsonSerializer.java | 4 ++-- .../impl/RegattaJsonSerializer.java | 6 +++--- .../jaxrs/api/LeaderboardsResourceV2.java | 6 +++--- .../gateway/jaxrs/api/RegattasResource.java | 19 ++++++++++--------- .../server/security/SailingViewerRole.java | 4 ++-- .../sse/security/shared/HasPermissions.java | 3 +++ .../shared/impl/SecuredSecurityTypes.java | 7 +++++++ 11 files changed, 44 insertions(+), 39 deletions(-) diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/security/SecuredDomainType.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/security/SecuredDomainType.java index 8e882d47a46..828c56e6e09 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/security/SecuredDomainType.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/security/SecuredDomainType.java @@ -6,6 +6,7 @@ import java.util.Set; import com.sap.sse.security.shared.HasPermissions; import com.sap.sse.security.shared.impl.HasPermissionsImpl; +import com.sap.sse.security.shared.impl.SecuredSecurityTypes; /** * Logical domain types in the "sailing" domain that require the user to have certain permissions @@ -61,22 +62,15 @@ public class SecuredDomainType extends HasPermissionsImpl { DefaultActions.CHANGE_ACL }; } - public static enum CompetitorAndBoatActions implements Action { - READ_PUBLIC; - - public static final Action[] READ_AND_READ_PUBLIC_ACTIONS = new Action[] { READ_PUBLIC, DefaultActions.READ }; - - private static final Action[] ALL_ACTIONS = new Action[] { READ_PUBLIC, DefaultActions.READ, + private static final Action[] ALL_ACTIONS_FOR_COMPETITOR_AND_BOAT = new Action[] { + SecuredSecurityTypes.PublicReadableActions.READ_PUBLIC, DefaultActions.READ, DefaultActions.CREATE, DefaultActions.UPDATE, DefaultActions.CHANGE_OWNERSHIP, DefaultActions.CHANGE_ACL }; - public static final Action[] MUTATION_ACTIONS = new Action[] { DefaultActions.CREATE, DefaultActions.UPDATE, - DefaultActions.CHANGE_OWNERSHIP, DefaultActions.CHANGE_ACL }; - }; + public static final HasPermissions COMPETITOR = new SecuredDomainType("COMPETITOR", + ALL_ACTIONS_FOR_COMPETITOR_AND_BOAT); - public static final HasPermissions COMPETITOR = new SecuredDomainType("COMPETITOR", CompetitorAndBoatActions.ALL_ACTIONS); - - public static final HasPermissions BOAT = new SecuredDomainType("BOAT", CompetitorAndBoatActions.ALL_ACTIONS); + public static final HasPermissions BOAT = new SecuredDomainType("BOAT", ALL_ACTIONS_FOR_COMPETITOR_AND_BOAT); public static final HasPermissions MEDIA_TRACK = new SecuredDomainType("MEDIA_TRACK"); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/user/profile/GetCompetitorAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/user/profile/GetCompetitorAction.java index 4b844f3532c..393aa032963 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/user/profile/GetCompetitorAction.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/user/profile/GetCompetitorAction.java @@ -5,11 +5,11 @@ import java.util.UUID; import com.google.gwt.core.shared.GwtIncompatible; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorAndBoatStore; -import com.sap.sailing.domain.common.security.SecuredDomainType.CompetitorAndBoatActions; import com.sap.sailing.gwt.home.communication.SailingAction; import com.sap.sailing.gwt.home.communication.SailingDispatchContext; import com.sap.sailing.gwt.home.communication.event.SimpleCompetitorWithIdDTO; import com.sap.sse.gwt.dispatch.shared.exceptions.DispatchException; +import com.sap.sse.security.shared.impl.SecuredSecurityTypes; /** * {@link SailingAction} implementation to load competitor data to be shown on the qr code page for the @@ -40,7 +40,7 @@ public class GetCompetitorAction implements SailingAction result; CompetitorAndBoatStore competitorStore = getService().getBaseDomainFactory().getCompetitorAndBoatStore(); - final HasPermissions.Action[] requiredActionsForRead = SecuredDomainType.CompetitorAndBoatActions.READ_AND_READ_PUBLIC_ACTIONS; + final HasPermissions.Action[] requiredActionsForRead = SecuredSecurityTypes.PublicReadableActions.READ_AND_READ_PUBLIC_ACTIONS; if (filterCompetitorsWithBoat == false && filterCompetitorsWithoutBoat == false) { @SuppressWarnings("unchecked") Iterable competitors = (Iterable) competitorStore.getAllCompetitors(); @@ -5923,7 +5923,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public Iterable getAllBoats() { - final HasPermissions.Action[] requiredActionsForRead = SecuredDomainType.CompetitorAndBoatActions.READ_AND_READ_PUBLIC_ACTIONS; + final HasPermissions.Action[] requiredActionsForRead = SecuredSecurityTypes.PublicReadableActions.READ_AND_READ_PUBLIC_ACTIONS; Iterable result = getSecurityService().mapAndFilterByAnyExplicitPermissionForCurrentUser( SecuredDomainType.BOAT, requiredActionsForRead, getService().getBaseDomainFactory().getCompetitorAndBoatStore().getBoats(), @@ -5935,7 +5935,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S public Iterable getStandaloneBoats() { List result = new ArrayList<>(); getSecurityService().filterObjectsWithAnyPermissionForCurrentUser(SecuredDomainType.BOAT, - SecuredDomainType.CompetitorAndBoatActions.READ_AND_READ_PUBLIC_ACTIONS, + SecuredSecurityTypes.PublicReadableActions.READ_AND_READ_PUBLIC_ACTIONS, getService().getBaseDomainFactory().getCompetitorAndBoatStore().getStandaloneBoats(), filteredObject -> result.add(convertToBoatDTO(filteredObject))); return result; diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorTrackWithEstimationDataJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorTrackWithEstimationDataJsonSerializer.java index 4c6bd073996..30a2695b5d8 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorTrackWithEstimationDataJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorTrackWithEstimationDataJsonSerializer.java @@ -10,7 +10,6 @@ import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.common.WindSource; import com.sap.sailing.domain.common.WindSourceType; -import com.sap.sailing.domain.common.security.SecuredDomainType; import com.sap.sailing.domain.common.tracking.GPSFixMoving; import com.sap.sailing.domain.maneuverdetection.impl.ManeuverDetectorImpl; import com.sap.sailing.domain.maneuverdetection.impl.TrackTimeInfo; @@ -23,6 +22,7 @@ import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; import com.sap.sse.common.impl.MillisecondsDurationImpl; import com.sap.sse.security.SecurityService; +import com.sap.sse.security.shared.impl.SecuredSecurityTypes; /** * @@ -84,7 +84,7 @@ public class CompetitorTrackWithEstimationDataJsonSerializer extends AbstractTra result.put(BYCOMPETITOR, byCompetitorJson); for (Competitor competitor : trackedRace.getRace().getCompetitors()) { if (securityService.hasCurrentUserAnyExplicitPermissions(competitor, - SecuredDomainType.CompetitorAndBoatActions.READ_AND_READ_PUBLIC_ACTIONS)) { + SecuredSecurityTypes.PublicReadableActions.READ_AND_READ_PUBLIC_ACTIONS)) { ManeuverDetectorImpl maneuverDetector = new ManeuverDetectorImpl(trackedRace, competitor); TrackTimeInfo trackTimeInfo = maneuverDetector.getTrackTimeInfo(); if (trackTimeInfo != null) { diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/RegattaJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/RegattaJsonSerializer.java index 87c1a7a6a0b..2c9eba81b05 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/RegattaJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/RegattaJsonSerializer.java @@ -7,9 +7,9 @@ import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.Series; -import com.sap.sailing.domain.common.security.SecuredDomainType; import com.sap.sailing.server.gateway.serialization.JsonSerializer; import com.sap.sse.security.SecurityService; +import com.sap.sse.security.shared.impl.SecuredSecurityTypes; public class RegattaJsonSerializer implements JsonSerializer { public static final String FIELD_NAME = "name"; @@ -65,7 +65,7 @@ public class RegattaJsonSerializer implements JsonSerializer { JSONArray competitorsJson = new JSONArray(); for (Competitor competitor : regatta.getAllCompetitors()) { if (securityService.hasCurrentUserAnyExplicitPermissions(competitor, - SecuredDomainType.CompetitorAndBoatActions.READ_AND_READ_PUBLIC_ACTIONS)) { + SecuredSecurityTypes.PublicReadableActions.READ_AND_READ_PUBLIC_ACTIONS)) { competitorsJson.add(competitorSerializer.serialize(competitor)); } } @@ -75,7 +75,7 @@ public class RegattaJsonSerializer implements JsonSerializer { JSONArray boatsJson = new JSONArray(); for (Boat boat : regatta.getAllBoats()) { if (securityService.hasCurrentUserAnyExplicitPermissions(boat, - SecuredDomainType.CompetitorAndBoatActions.READ_AND_READ_PUBLIC_ACTIONS)) { + SecuredSecurityTypes.PublicReadableActions.READ_AND_READ_PUBLIC_ACTIONS)) { boatsJson.add(boatSerializer.serialize(boat)); } } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResourceV2.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResourceV2.java index d160b5df2c4..517e0929e1a 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResourceV2.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResourceV2.java @@ -42,7 +42,6 @@ import com.sap.sailing.domain.common.dto.LeaderboardDTO; import com.sap.sailing.domain.common.dto.LeaderboardEntryDTO; import com.sap.sailing.domain.common.dto.LeaderboardRowDTO; import com.sap.sailing.domain.common.dto.LegEntryDTO; -import com.sap.sailing.domain.common.security.SecuredDomainType; import com.sap.sailing.domain.common.sharding.ShardingType; import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.sharding.ShardingContext; @@ -54,6 +53,7 @@ import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util.Pair; import com.sap.sse.security.shared.HasPermissions.DefaultActions; +import com.sap.sse.security.shared.impl.SecuredSecurityTypes; @Path("/v2/leaderboards") public class LeaderboardsResourceV2 extends AbstractLeaderboardsResource { @@ -148,7 +148,7 @@ public class LeaderboardsResourceV2 extends AbstractLeaderboardsResource { List filteredCompetitorsFromBestToWorst = new ArrayList<>(); competitorsFromBestToWorst.forEach(competitor -> { if (SecurityUtils.getSubject().isPermitted(competitor.getIdentifier() - .getStringPermission(SecuredDomainType.CompetitorAndBoatActions.READ_PUBLIC)) + .getStringPermission(SecuredSecurityTypes.PublicReadableActions.READ_PUBLIC)) || SecurityUtils.getSubject() .isPermitted(competitor.getIdentifier().getStringPermission(DefaultActions.READ))) { filteredCompetitorsFromBestToWorst.add(competitor); @@ -178,7 +178,7 @@ public class LeaderboardsResourceV2 extends AbstractLeaderboardsResource { leaderboardDTO.competitors.forEach(competitor -> { if (SecurityUtils.getSubject() .isPermitted(competitor.getIdentifier() - .getStringPermission(SecuredDomainType.CompetitorAndBoatActions.READ_PUBLIC)) + .getStringPermission(SecuredSecurityTypes.PublicReadableActions.READ_PUBLIC)) || SecurityUtils.getSubject() .isPermitted(competitor.getIdentifier().getStringPermission(DefaultActions.READ))) { filteredCompetitors.add(competitor); 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 25a2b2cda40..768e179b413 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 @@ -142,6 +142,7 @@ import com.sap.sse.common.util.RoundingUtil; import com.sap.sse.datamining.shared.impl.PredefinedQueryIdentifier; import com.sap.sse.security.shared.HasPermissions.DefaultActions; import com.sap.sse.security.shared.OwnershipAnnotation; +import com.sap.sse.security.shared.impl.SecuredSecurityTypes; import com.sap.sse.security.shared.impl.User; @Path("/v1/regattas") @@ -331,7 +332,7 @@ public class RegattasResource extends AbstractSailingServerResource { final JSONArray result = new JSONArray(); for (final Competitor competitor : regatta.getAllCompetitors()) { if (getSecurityService().hasCurrentUserAnyExplicitPermissions(competitor, - SecuredDomainType.CompetitorAndBoatActions.READ_AND_READ_PUBLIC_ACTIONS)) { + SecuredSecurityTypes.PublicReadableActions.READ_AND_READ_PUBLIC_ACTIONS)) { result.add(competitorSerializer.serialize(competitor)); } } @@ -364,7 +365,7 @@ public class RegattasResource extends AbstractSailingServerResource { response = getBadCompetitorIdResponse(competitorId); } else { getSecurityService().checkCurrentUserAnyExplicitPermissions(competitor, - SecuredDomainType.CompetitorAndBoatActions.READ_AND_READ_PUBLIC_ACTIONS); + SecuredSecurityTypes.PublicReadableActions.READ_AND_READ_PUBLIC_ACTIONS); regatta.registerCompetitor(competitor); response = Response.ok().build(); } @@ -609,7 +610,7 @@ public class RegattasResource extends AbstractSailingServerResource { response = Response.status(Status.NOT_FOUND).entity("Boat is not valid").type(MediaType.TEXT_PLAIN).build(); } else { getSecurityService().checkCurrentUserAnyExplicitPermissions(boat, - SecuredDomainType.CompetitorAndBoatActions.READ_AND_READ_PUBLIC_ACTIONS); + SecuredSecurityTypes.PublicReadableActions.READ_AND_READ_PUBLIC_ACTIONS); response = createAndAddCompetitor(regattaName, nationalityThreeLetterIOCCode, displayColor, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMileAsMillis, searchTag, competitorName, competitorShortName, competitorEmail, flagImageURI, teamImageURI, t -> boat, deviceUuid, @@ -665,7 +666,7 @@ public class RegattasResource extends AbstractSailingServerResource { response = getBadCompetitorIdResponse(competitorId); } else { getSecurityService().checkCurrentUserAnyExplicitPermissions(competitor, - SecuredDomainType.CompetitorAndBoatActions.READ_AND_READ_PUBLIC_ACTIONS); + SecuredSecurityTypes.PublicReadableActions.READ_AND_READ_PUBLIC_ACTIONS); regatta.deregisterCompetitor(competitor); response = Response.ok().build(); } @@ -728,7 +729,7 @@ public class RegattasResource extends AbstractSailingServerResource { JSONArray jsonCompetitors = new JSONArray(); for (Competitor competitor : trackedRace.getRace().getCompetitors()) { if (getSecurityService().hasCurrentUserAnyExplicitPermissions(competitor, - SecuredDomainType.CompetitorAndBoatActions.READ_AND_READ_PUBLIC_ACTIONS)) { + SecuredSecurityTypes.PublicReadableActions.READ_AND_READ_PUBLIC_ACTIONS)) { if (competitorIds == null || competitorIds.isEmpty() || competitorIds.contains(competitor.getId().toString())) { JSONObject jsonCompetitor = new JSONObject(); @@ -1405,7 +1406,7 @@ public class RegattasResource extends AbstractSailingServerResource { for (Competitor competitor : competitors) { if (getSecurityService().hasCurrentUserAnyExplicitPermissions(competitor, - SecuredDomainType.CompetitorAndBoatActions.READ_AND_READ_PUBLIC_ACTIONS)) { + SecuredSecurityTypes.PublicReadableActions.READ_AND_READ_PUBLIC_ACTIONS)) { if (competitorFilter == null || competitor.getId().equals(competitorFilter)) { Iterable maneuversForCompetitor = trackedRace.getManeuvers(competitor, startTime, endTime, false); data.add(new Pair>(competitor, maneuversForCompetitor)); @@ -1601,7 +1602,7 @@ public class RegattasResource extends AbstractSailingServerResource { Map ranks = leg.getRanks(timePoint); for (Competitor competitor : trackedRace.getRace().getCompetitors()) { if (getSecurityService().hasCurrentUserAnyExplicitPermissions(competitor, - SecuredDomainType.CompetitorAndBoatActions.READ_AND_READ_PUBLIC_ACTIONS)) { + SecuredSecurityTypes.PublicReadableActions.READ_AND_READ_PUBLIC_ACTIONS)) { JSONObject jsonCompetitorInLeg = new JSONObject(); TrackedLegOfCompetitor trackedLegOfCompetitor = leg.getTrackedLeg(competitor); if (trackedLegOfCompetitor != null) { @@ -1769,7 +1770,7 @@ public class RegattasResource extends AbstractSailingServerResource { Integer overallRank = 1; for (Competitor competitor : overallRanking) { if (getSecurityService().hasCurrentUserAnyExplicitPermissions(competitor, - SecuredDomainType.CompetitorAndBoatActions.READ_AND_READ_PUBLIC_ACTIONS)) { + SecuredSecurityTypes.PublicReadableActions.READ_AND_READ_PUBLIC_ACTIONS)) { overallRankPerCompetitor.put(competitor, overallRank++); } } @@ -1777,7 +1778,7 @@ public class RegattasResource extends AbstractSailingServerResource { Integer rank = 1; for (Competitor competitor : competitorsFromBestToWorst) { if (getSecurityService().hasCurrentUserAnyExplicitPermissions(competitor, - SecuredDomainType.CompetitorAndBoatActions.READ_AND_READ_PUBLIC_ACTIONS)) { + SecuredSecurityTypes.PublicReadableActions.READ_AND_READ_PUBLIC_ACTIONS)) { JSONObject jsonCompetitorInLeg = new JSONObject(); if (topN != null && topN > 0 && rank > topN) { diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/security/SailingViewerRole.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/security/SailingViewerRole.java index 45a183b059b..916e4507a75 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/security/SailingViewerRole.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/security/SailingViewerRole.java @@ -1,10 +1,10 @@ package com.sap.sailing.server.security; import com.sap.sailing.domain.common.security.SecuredDomainType; -import com.sap.sailing.domain.common.security.SecuredDomainType.CompetitorAndBoatActions; import com.sap.sse.security.shared.HasPermissions.DefaultActions; import com.sap.sse.security.shared.RolePrototype; import com.sap.sse.security.shared.WildcardPermission; +import com.sap.sse.security.shared.impl.SecuredSecurityTypes; /** * Specifies a role that when associated to a user gives read access to the sailing domain parts needed for the home @@ -20,7 +20,7 @@ public class SailingViewerRole extends RolePrototype { WildcardPermission.builder().withTypes(SecuredDomainType.EVENT, SecuredDomainType.LEADERBOARD_GROUP, SecuredDomainType.LEADERBOARD, SecuredDomainType.REGATTA, SecuredDomainType.TRACKED_RACE) .withActions(DefaultActions.READ).build(), WildcardPermission.builder().withTypes(SecuredDomainType.COMPETITOR, SecuredDomainType.BOAT) - .withActions(CompetitorAndBoatActions.READ_PUBLIC).build(), + .withActions(SecuredSecurityTypes.PublicReadableActions.READ_PUBLIC).build(), WildcardPermission.builder().withTypes(SecuredDomainType.COMPETITOR, SecuredDomainType.BOAT) .withActions(DefaultActions.READ).build()); } diff --git a/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/HasPermissions.java b/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/HasPermissions.java index 54f147bf397..9e900166a5c 100644 --- a/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/HasPermissions.java +++ b/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/HasPermissions.java @@ -119,6 +119,9 @@ public interface HasPermissions { public static final Action[] MUTATION_ACTIONS = new Action[] { CREATE, UPDATE, DELETE, CHANGE_OWNERSHIP, CHANGE_ACL }; + + public static final Action[] MUTATION_ACTIONS_FOR_NON_DELETABLE_TYPES = new Action[] { DefaultActions.CREATE, + DefaultActions.UPDATE, DefaultActions.CHANGE_OWNERSHIP, DefaultActions.CHANGE_ACL }; /** * Returns all {@link DefaultActions} plus the {@code actions} passed, combined in one new array diff --git a/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/impl/SecuredSecurityTypes.java b/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/impl/SecuredSecurityTypes.java index 2f588c4761d..5bea85e76c1 100755 --- a/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/impl/SecuredSecurityTypes.java +++ b/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/impl/SecuredSecurityTypes.java @@ -32,6 +32,13 @@ public class SecuredSecurityTypes extends HasPermissionsImpl { return Collections.unmodifiableSet(allInstances); } + public static enum PublicReadableActions implements Action { + READ_PUBLIC; + + public static final Action[] READ_AND_READ_PUBLIC_ACTIONS = new Action[] { READ_PUBLIC, DefaultActions.READ }; + }; + + public static enum UserActions implements Action { /** Update a user's password without knowing the old password. */ FORCE_OVERWRITE_PASSWORD From d180073a262bcc78e06a2fdee8c628793c284d55 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Thu, 7 Mar 2019 17:10:57 +0100 Subject: [PATCH 04/26] Bug 4397: added READ_PUBLIC action to UserRole --- .../src/com/sap/sse/security/shared/UserRole.java | 5 ++++- .../sap/sse/security/shared/impl/SecuredSecurityTypes.java | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/UserRole.java b/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/UserRole.java index 2a5adb21d05..050f7481d55 100755 --- a/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/UserRole.java +++ b/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/UserRole.java @@ -1,6 +1,7 @@ package com.sap.sse.security.shared; import com.sap.sse.security.shared.HasPermissions.DefaultActions; +import com.sap.sse.security.shared.impl.SecuredSecurityTypes; public class UserRole extends RolePrototype { private static final long serialVersionUID = 3291793984984443193L; @@ -9,7 +10,9 @@ public class UserRole extends RolePrototype { UserRole() { super("user", "ad1d5148-b13d-4464-90c4-7c396e4d4e2e", - WildcardPermission.builder().withActions(DefaultActions.values()).build()); + WildcardPermission.builder() + .withActions(DefaultActions.plus(SecuredSecurityTypes.PublicReadableActions.READ_PUBLIC)) + .build()); } public static UserRole getInstance() { diff --git a/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/impl/SecuredSecurityTypes.java b/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/impl/SecuredSecurityTypes.java index 5bea85e76c1..c6276e9362c 100755 --- a/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/impl/SecuredSecurityTypes.java +++ b/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/impl/SecuredSecurityTypes.java @@ -47,7 +47,7 @@ public class SecuredSecurityTypes extends HasPermissionsImpl { * type-relative identifier is the {@link User#getName() username}. */ public static final HasPermissions USER = new SecuredSecurityTypes("USER", DefaultActions - .plus(UserActions.FORCE_OVERWRITE_PASSWORD)); + .plus(UserActions.FORCE_OVERWRITE_PASSWORD, PublicReadableActions.READ_PUBLIC)); /** * type-relative identifier is the {@link RoleDefinition#getId() role ID's} string representation From a2c7303c1644cb4882bf41c13d53fb6733667244 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Thu, 7 Mar 2019 17:23:37 +0100 Subject: [PATCH 05/26] Bug 4933: added READ_PUBLIC permission checks for retrieving users in back end in UserManagementService and SecurityResource --- .../ui/server/UserManagementServiceImpl.java | 17 +++++++++++++---- .../security/jaxrs/api/SecurityResource.java | 5 ++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/server/UserManagementServiceImpl.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/server/UserManagementServiceImpl.java index 0daf0e1a1a3..be698effce8 100644 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/server/UserManagementServiceImpl.java +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/server/UserManagementServiceImpl.java @@ -322,10 +322,15 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U @Override public UserDTO getUserByName(String username) throws UnauthorizedException { final User user = getSecurityService().getUserByName(username); - if (user == null || SecurityUtils.getSubject().isPermitted(SecuredSecurityTypes.USER.getStringPermissionForObject(DefaultActions.READ, user))) { - return user==null?null:securityDTOFactory.createUserDTOFromUser(user, getSecurityService()); + if (user == null + || SecurityUtils.getSubject() + .isPermitted(SecuredSecurityTypes.USER.getStringPermissionForObject(DefaultActions.READ, user)) + || SecurityUtils.getSubject().isPermitted(SecuredSecurityTypes.USER + .getStringPermissionForObject(SecuredSecurityTypes.PublicReadableActions.READ_PUBLIC, user))) { + // TODO: pruning when current user only has READ_PUBLIC permission + return user == null ? null : securityDTOFactory.createUserDTOFromUser(user, getSecurityService()); } else { - throw new UnauthorizedException("Not permitted to read user "+username); + throw new UnauthorizedException("Not permitted to read user " + username); } } @@ -438,7 +443,11 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U public Collection getUserList() throws UnauthorizedException { List users = new ArrayList<>(); for (User u : getSecurityService().getUserList()) { - if (SecurityUtils.getSubject().isPermitted(SecuredSecurityTypes.USER.getStringPermissionForObject(DefaultActions.READ, u))) { + if (SecurityUtils.getSubject() + .isPermitted(SecuredSecurityTypes.USER.getStringPermissionForObject(DefaultActions.READ, u)) + || SecurityUtils.getSubject().isPermitted(SecuredSecurityTypes.USER + .getStringPermissionForObject(SecuredSecurityTypes.PublicReadableActions.READ_PUBLIC, u))) { + // TODO: pruning if subject only has READ_PUBLIC permission final UserDTO userDTO = getUserDTOWithFilteredRolesAndPermissions(u); users.add(userDTO); } diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/SecurityResource.java b/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/SecurityResource.java index 27e03e180f0..f1b18214a5e 100644 --- a/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/SecurityResource.java +++ b/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/SecurityResource.java @@ -26,6 +26,7 @@ import com.sap.sse.common.Util; import com.sap.sse.common.mail.MailException; import com.sap.sse.security.jaxrs.AbstractSecurityResource; import com.sap.sse.security.shared.UserManagementException; +import com.sap.sse.security.shared.impl.SecuredSecurityTypes; import com.sap.sse.security.shared.impl.User; import com.sun.jersey.api.client.ClientResponse.Status; @@ -156,7 +157,9 @@ public class SecurityResource extends AbstractSecurityResource { final User user = getService().getUserByName(username == null ? subject.getPrincipal().toString() : username); if (user == null) { return Response.status(Status.PRECONDITION_FAILED).entity("User "+username+" not known").build(); - } else if (!getService().hasCurrentUserReadPermission(user)) { + } else if (!(getService().hasCurrentUserReadPermission(user) && getService() + .hasCurrentUserAnyExplicitPermissions(user, SecuredSecurityTypes.PublicReadableActions.READ_PUBLIC))) { + // TODO: pruning when current user only has READ_PUBLIC return Response.status(Status.UNAUTHORIZED).build(); } else { JSONObject result = new JSONObject(); From b8519da010869c98081aff880bc4739e82f72f50 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Thu, 7 Mar 2019 17:52:07 +0100 Subject: [PATCH 06/26] fixed pruning for competitors and boats --- .../src/com/sap/sse/security/impl/SecurityServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/impl/SecurityServiceImpl.java b/java/com.sap.sse.security/src/com/sap/sse/security/impl/SecurityServiceImpl.java index c9931f42f98..7745e0a8460 100644 --- a/java/com.sap.sse.security/src/com/sap/sse/security/impl/SecurityServiceImpl.java +++ b/java/com.sap.sse.security/src/com/sap/sse/security/impl/SecurityServiceImpl.java @@ -1789,7 +1789,7 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat HasPermissions permittedObject, HasPermissions.Action[] actions, Iterable objectsToFilter, Consumer filteredObjectsConsumer) { objectsToFilter.forEach(objectToCheck -> { - boolean isPermitted = actions.length > 0; + boolean isPermitted = false; for (int i = 0; i < actions.length; i++) { if (SecurityUtils.getSubject() .isPermitted(permittedObject.getStringPermissionForObject(actions[i], objectToCheck))) { From 0cae98b32fe0686c4610f92fdf1d39d12b28e48a Mon Sep 17 00:00:00 2001 From: "service.tip.git" Date: Thu, 7 Mar 2019 17:00:02 +0000 Subject: [PATCH 07/26] [INTERNAL] Translation delivery: commit by SLS Change-Id: Id5cfc18d1fc6544937b7b4f51f206a4c224d6eb0 --- .../com/sap/sailing/gwt/ui/client/StringMessages_es.properties | 2 +- .../com/sap/sailing/gwt/ui/client/StringMessages_fr.properties | 2 +- .../com/sap/sailing/gwt/ui/client/StringMessages_ja.properties | 2 +- .../com/sap/sailing/gwt/ui/client/StringMessages_pt.properties | 2 +- .../com/sap/sailing/gwt/ui/client/StringMessages_ru.properties | 2 +- .../com/sap/sailing/gwt/ui/client/StringMessages_zh.properties | 2 +- 6 files changed, 6 insertions(+), 6 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 cf582dbda48..f5ed92e7dee 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 @@ -236,7 +236,7 @@ raceIsKnownToStartUpwind=La carrera empieza con ceñida events=Eventos pairingList=Lista de emparejamientos pairingLists=Listas de emparejamientos -pairingListCreationInfo=Inicialmente se calculará una plantilla que contenga solo los números de los competidores y que pueda aplicarse a otras clasificaciones. Si el recuento de competidores no es divisible por recuento de embarcaciones sin remanente, se introducirán marcadores de posición en blanco en la lista de emparejamientos. \ Además, si el recuento de competidores difiere del recuento de competidores registrado en la clasificación real, la lista de emparejamientos no podrá aplicarse a los registros de la carrera. \ El recuento de flights, que se utiliza para generar una lista de emparejamientos, está definido por el número de flights de la clasificación que no son carreras de medalla. \ Cuando se utilizan repeticiones de flight, se pueden repetir asignaciones de flights (por ejemplo, 15 flights con 3 repeticiones de flight: 5 asignaciones de flight únicas que se repetirán 3 veces cada una de ellas). \ Un factor de cambio de embarcación equivalente a 0 da como resultado una asignación bien distribuida de competidores y embarcaciones, considerando que el máximo (número de flights) provoca menos cambios de embarcación, dado que los competidores navegan en la misma embarcación para dos flotas, uno detrás de otro, en diferentes flights. +pairingListCreationInfo=Inicialmente se calculará una plantilla que contenga solo los números de los competidores y que pueda aplicarse a otras clasificaciones. Si el recuento de competidores no es divisible por recuento de embarcaciones sin remanente, se introducirán marcadores de posición en blanco en la lista de emparejamientos. \ Además, si el recuento de competidores difiere del recuento de competidores registrado en la clasificación real, la lista de emparejamientos no podrá aplicarse a los registros de la carrera. \ El recuento de flights, que se utiliza para generar una lista de emparejamientos, está definido por el número de flights de la clasificación que no son carreras de medalla. \ Cuando se utilizan repeticiones de flight, se pueden repetir asignaciones de flights (por ejemplo, 15 flights con 3 repeticiones de flight: 5 asignaciones de flight únicas que se repetirán 3 veces cada una de ellas). \ Un factor de cambio de embarcación equivalente a 0 da como resultado una asignación bien distribuida de competidores y embarcaciones, considerando que el máximo (número de flights) provoca menos cambios de embarcación aumentando las posibilidades de que un competidor navegue con la misma embarcación en dos carreras contiguas a través de un límite de flights. setCompetitors=Fije el recuento de competidores: setBoatChangeFactor=Fije el factor de cambio de embarcación: seriesHint=Seleccione una o más series que deberían estar en una lista de emparejamientos: 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 c0badc9ec42..8932083ac25 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 @@ -236,7 +236,7 @@ raceIsKnownToStartUpwind=La course a commencé avec une portion de parcours au v events=Manifestations pairingList=Liste d''appariement pairingLists=Listes d''appariement -pairingListCreationInfo=Tout d''abord, un modèle contenant uniquement le nombre de concurrents sera calculé. Il pourra être appliqué à d''autres palmarès. Si la division du nombre de concurrents par le nombre de bateaux ne permet pas d''obtenir un nombre entier, des espaces réservés vides seront ajoutés à la liste d''appariement. \ En outre, si le nombre de concurrents ne correspond pas au nombre de concurrents inscrits au palmarès actuel, la liste d''appariement ne pourra pas être appliquée aux journaux de course. \ Le nombre de flights (matchs) utilisé pour générer une liste d''appariement est défini par tous les flights du palmarès, hors courses médaillées. \ En cas de répétition des flights, les affectations de flights peuvent être répétées (par exemple, 15 flights avec 3 répétitions : 5 affectations de flights uniques, et chacun sera répété 3 fois). \ Un facteur de changement de bateau équivalent à 0 permet une répartition correcte des concurrents sur les bateaux, alors que le nombre de flights maximum implique moins de changements de bateaux car les concurrents naviguent sur un même bateau pour deux flottes l''une après l''autre sur des flights différents. +pairingListCreationInfo=Tout d''abord, un modèle contenant uniquement le nombre de concurrents sera calculé. Il pourra être appliqué à d''autres palmarès. Si la division du nombre de concurrents par le nombre de bateaux ne permet pas d''obtenir un nombre entier, des espaces réservés vides seront ajoutés à la liste d''appariement. \ En outre, si le nombre de concurrents ne correspond pas au nombre de concurrents inscrits au palmarès actuel, la liste d''appariement ne pourra pas être appliquée aux journaux de course. \ Le nombre de flights (matchs) utilisé pour générer une liste d''appariement est défini par tous les flights du palmarès, hors courses médaillées. \ En cas de répétition des flights, les affectations de flights peuvent être répétées (par exemple, 15 flights avec 3 répétitions : 5 affectations de flights uniques, et chacun sera répété 3 fois). \ Un facteur de changement de bateau équivalent à 0 permet une répartition correcte des concurrents sur les bateaux, alors que le nombre de flights maximum implique moins de changements de bateaux en augmentant les chances qu''un concurrent navigue sur un même bateau pour deux courses consécutives trans-flight. setCompetitors=Veuillez définir le nombre de concurrents : setBoatChangeFactor=Veuillez définir le facteur de changement de bateau : seriesHint=Veuillez sélectionner une ou plusieurs séries à ajouter à une liste de paires : 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 616cd052797..ada6b81e69e 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 @@ -236,7 +236,7 @@ raceIsKnownToStartUpwind=アップウィンドレグでレーススタート events=イベント pairingList=対戦表 pairingLists=対戦表 -pairingListCreationInfo=まず最初に、競技者番号のみが含まれていて、他のリーダーボードに適用できるテンプレートがすべて計算されます。競技者カウントが艇カウントで割り切れない場合、空のプレースホルダーが対戦表に入力されます。 \ また、競技者カウントが実際のリーダーボードにある登録済の競技者カウントと等しくない場合、対戦表をレースログに適用することはできません。 \ 対戦表を生成するために使用されるフライトのカウントは、リーダーボードにあるメダルレースでないフライトの回数によって設定されます。 \ フライト繰返の使用時に、フライト割当を繰り返すことができます (例: 3 つのフライト繰返がある 15 回のフライトでは、別々の 5 つのフライト割当でそれぞれが 3 回繰り返されます)。 \ 艇変更係数が 0 に等しければ、艇への競技者の割当がうまく配分されることにつながり、一方、最大 (フライト回数) になると、別のフライトだが互いに前後している 2 つのフリートで競技者が同一艇で帆走するため艇変更が少なくなることにつながります。 +pairingListCreationInfo=まず最初に、競技者番号のみが含まれていて、他のリーダーボードに適用できるテンプレートがすべて計算されます。競技者カウントが艇カウントで割り切れない場合、空のプレースホルダーが対戦表に入力されます。 \ また、競技者カウントが実際のリーダーボードにある登録済の競技者カウントと等しくない場合、対戦表をレースログに適用することはできません。 \ 対戦表を生成するために使用されるフライトのカウントは、リーダーボードにあるメダルレースでないフライトの回数によって設定されます。 \ フライト繰返の使用時に、フライト割当を繰り返すことができます (例: 3 つのフライト繰返がある 15 回のフライトでは、別々の 5 つのフライト割当でそれぞれが 3 回繰り返されます)。 \ 艇変更係数が 0 に等しければ、艇への競技者の割当がうまく配分されることにつながり、一方、最大 (フライト回数) になると、フライトの境界を超えて隣接している 2 つのレースで競技者が同一艇で帆走する可能性が高くなることで艇変更がより少なくなります。 setCompetitors=競技者カウントを設定してください: setBoatChangeFactor=艇変更係数を設定してください: seriesHint=対戦表にあることが必要なシリーズを 1 つ以上選択してください: 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 2c1ef6f5c14..4fefce81d45 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 @@ -236,7 +236,7 @@ raceIsKnownToStartUpwind=A corrida começa com perna de contravento events=Eventos pairingList=Lista de pares pairingLists=Listas de pares -pairingListCreationInfo=Primeiro será calculado um modelo que contém somente os números dos competidores e pode ser aplicado a outros painéis de classificação. Se contagem de competidores não for divisível pela contagem de barcos sem restante, os caracteres de preenchimento em branco serão inseridos na lista de pares. \ Além disso, se a contagem de competidores for diferente da contagem de competidores registrado no painel de classificação real, a lista de pares não pode ser aplicada aos registros das corridas. \ A contagem de voos, que é utilizado para gerar uma lista de pares, é definida pelo número de voos no painel de classificação que não sejam corridas para medalha. \ Ao utilizar repetições de voo, as atribuições de voo podem ser repetidas (por exemplo, 15 voos com 3 repetições de voo: 5 atribuições de voo únicas e cada uma será repetida 3 vezes). \ Um fator de mudança de barco igual a 0 leva a uma atribuição bem distribuída de competidores a barcos, sendo que o (número de voos) máximo leva a menos mudanças de barco devido a competidores que navegam no mesmo barco para duas flotilhas atrás uma da outra em diferentes voos. +pairingListCreationInfo=Primeiro será calculado um modelo que contém somente os números dos competidores e pode ser aplicado a outros painéis de classificação. Se contagem de competidores não for divisível pela contagem de barcos sem restante, os caracteres de preenchimento em branco serão inseridos na lista de pares. \ Além disso, se a contagem de competidores for diferente da contagem de competidores registrados no painel de classificação real, a lista de pares não pode ser aplicada aos registros das corridas. \ A contagem de voos, que é utilizada para gerar uma lista de pares, é definida pelo número de voos no painel de classificação que não sejam corridas para medalha. \ Ao utilizar repetições de voo, as atribuições de voo podem ser repetidas (por exemplo, 15 voos com 3 repetições de voo: 5 atribuições de voo únicas e cada uma será repetida 3 vezes). \ Um fator de mudança de barco igual a 0 leva a uma atribuição bem distribuída de competidores a barcos, sendo que o (número de voos) máximo leva a menos mudanças de barco aumentando as hipóteses de um competidor navegar no mesmo barco em duas corridas contínuas além do limite do voo. setCompetitors=Defina a contagem dos competidores: setBoatChangeFactor=Defina o fator de mudança de barco: seriesHint=Selecione uma ou mais séries que devam estar em uma lista de pares: 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 b62aa2f6189..b166b1c9bd9 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 @@ -236,7 +236,7 @@ raceIsKnownToStartUpwind=Гонка начинается против ветра events=События pairingList=Список пар pairingLists=Списки пар -pairingListCreationInfo=Первым будет рассчитан шаблон, который содержит только номера участников и может быть применен к другим таблицам лидеров. Если число участников не делится на число лодок без остатка, в списке пар будут пустые места. \ Если число участников не равно числу зарегистрированных участников в фактической таблице лидеров, список пар не может быть применен к журналам гонки. \ Для генерирования списка пар используется число всех флайтов таблицы лидеров, не являющихся гонками на медали. \ Если используются повторы флайтов, то присвоения флайтов могут повторяться (например, 15 флайтов с 3 повторами: 5 уникальных присвоений флайтов, каждый из которых повторяется 3 раза). \ Результатом нулевого коэффициента смены лодки является хорошее распределение присвоений участников лодкам, то есть максимум (число флайтов) ведет к меньшему числу смен лодок, поскольку участники плывут на одной и той же лодке двух флотов друг за другом в разных флайтах. +pairingListCreationInfo=Первым будет рассчитан шаблон, который содержит только номера участников и может быть применен к другим таблицам лидеров. Если число участников не делится на число лодок без остатка, в списке пар будут пустые места. \ Если число участников не равно числу зарегистрированных участников в фактической таблице лидеров, список пар не может быть применен к журналам гонки. \ Для генерирования списка пар используется число всех флайтов таблицы лидеров, не являющихся гонками на медали. \ Если используются повторы флайтов, то присвоения флайтов могут повторяться (например, 15 флайтов с 3 повторами: 5 уникальных присвоений флайтов, каждый из которых повторяется 3 раза). \ Результатом нулевого коэффициента смены лодки является хорошее распределение участников по лодкам, то есть максимум (число флайтов) ведет к меньшему числу смен лодок, и это увеличивает шансы, что участник будет плыть на одной и той же лодке в двух смежных гонках до окончания флайта. setCompetitors=Укажите число участников: setBoatChangeFactor=Укажите коэффициент смены лодки: seriesHint=Выберите не менее одной серии для списка пар: 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 aebe76081da..b2373c52e06 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 @@ -236,7 +236,7 @@ raceIsKnownToStartUpwind=比赛轮次从迎风航段开始 events=活动 pairingList=配对清单 pairingLists=配对清单 -pairingListCreationInfo=首先,将计算仅包含参赛队数并且可以应用到其他积分榜的模板。如果参赛队数量无法被船只数量除尽,则在配对清单中输入空占位符。\ 此外,如果参赛队数量不等于实际积分榜中注册的参赛队数量,配对清单无法应用到比赛轮次日志。\ 用于生成配对清单的航程数由积分榜中不是奖牌轮的航程数定义。\ 使用航程重复时,可以重复航程分配(例如,有 3 个航程重复的 15 个航程:5 个独特的航程分配,每个重复 3 次)。\ 船只更换系数等于 0 导致向船只平均分配参赛队,而最大(航程数)导致船只更换次数减少,因为不同航程中背后两个船队的参赛队在同一船只上航行。 +pairingListCreationInfo=首先,将计算仅包含参赛队数并且可以应用到其他积分榜的模板。如果参赛队数量无法被船只数量除尽,则在配对清单中输入空占位符。\ 此外,如果参赛队数量不等于实际积分榜中注册的参赛队数量,配对清单无法应用到比赛轮次日志。\ 用于生成配对清单的航程数由积分榜中不是奖牌轮的航程数定义。\ 使用航程重复时,可以重复航程分配(例如,有 3 个航程重复的 15 个航程:5 个独特的航程分配,每个重复 3 次)。\ 船只更换系数等于 0 导致向船只平均分配参赛队,而最大值(航程数)通过提高参赛队在两个连续的比赛轮次驾驶同一船只驶过航程边界的机会来减少换船次数。 setCompetitors=请设置参赛队数量: setBoatChangeFactor=请设置船只更换系数: seriesHint=请选择一场或多场应位于配对清单的系列赛: From cbdef5b6d1f5f02068e3124901340888b3a97c73 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Thu, 7 Mar 2019 18:04:48 +0100 Subject: [PATCH 08/26] fixed missing null check --- .../server/gateway/jaxrs/AbstractSailingServerResource.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/AbstractSailingServerResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/AbstractSailingServerResource.java index a50a475505c..56e4a5ccbd5 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/AbstractSailingServerResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/AbstractSailingServerResource.java @@ -118,6 +118,9 @@ public abstract class AbstractSailingServerResource { * If the leaderboard can be resolved to a regatta, and the given secret is correct, return true */ protected boolean skipChecksDueToCorrectSecret(String leaderboardName, String secret) { + if (leaderboardName == null && secret == null) { + return false; + } Regatta regatta = getService().getRegattaByName(leaderboardName); if (regatta == null && secret != null) { logger.warning("Attempt to skip security checks using regatta secret \"" + secret + "\" for leaderboard \"" From caffc8a11e43a672bc2df42c39319c35aaf867bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20B=C3=B6rnert?= Date: Thu, 7 Mar 2019 18:08:05 +0100 Subject: [PATCH 09/26] improved checks for windpanel --- .../gwt/ui/adminconsole/WindPanel.java | 83 +++++++++++++++++-- .../gwt/ui/server/SailingServiceImpl.java | 7 +- .../windimport/AbstractWindImportServlet.java | 4 + .../windimport/AbstractWindImporter.java | 3 - 4 files changed, 87 insertions(+), 10 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java index 8cdd644b67c..fafb5435cc4 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java @@ -55,6 +55,7 @@ import com.sap.sailing.domain.common.WindSource; import com.sap.sailing.domain.common.WindSourceType; import com.sap.sailing.domain.common.dto.RaceDTO; import com.sap.sailing.domain.common.impl.WindSourceImpl; +import com.sap.sailing.domain.common.security.SecuredDomainType; import com.sap.sailing.gwt.ui.adminconsole.WindImportResult.RaceEntry; import com.sap.sailing.gwt.ui.client.RegattaRefresher; import com.sap.sailing.gwt.ui.client.RegattasDisplayer; @@ -75,7 +76,10 @@ import com.sap.sse.gwt.client.async.MarkedAsyncCallback; import com.sap.sse.gwt.client.celltable.BaseCelltable; import com.sap.sse.gwt.client.celltable.RefreshableMultiSelectionModel; import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback; +import com.sap.sse.security.shared.HasPermissions.DefaultActions; +import com.sap.sse.security.shared.dto.UserDTO; import com.sap.sse.security.ui.client.UserService; +import com.sap.sse.security.ui.client.UserStatusEventHandler; /** * Displays a table of currently tracked races. The user can configure whether a race @@ -120,6 +124,18 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe * will be forwarded to those objects contained in this collection. */ private final Set containedRegattaDisplayers; + + private CaptionPanel expeditionImportPanel; + + private CaptionPanel gribImportPanel; + + private CaptionPanel nmeaImportPanel; + + private CaptionPanel bravoImportPanel; + + private CaptionPanel igtimiImportPanel; + + private CaptionPanel expeditionAllInOneImporterPanel; public WindPanel(final SailingServiceAsync sailingService, UserService userService, AsyncActionsExecutor asyncActionsExecutor, ErrorReporter errorReporter, final StringMessages stringMessages) { @@ -163,6 +179,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe @Override public void onSelectionChange(SelectionChangeEvent event) { updateWindDisplay(); + updateVisibilityStateForPanels(); } }); windCaptionPanel = new CaptionPanel(stringMessages.wind()); @@ -278,19 +295,73 @@ public class WindPanel extends FormPanel implements RegattasDisplayer, WindShowe rawWindFixesTable.addColumnSortHandler(columnSortHandler); rawWindFixesTable.getColumnSortList().push(timeColumn); windFixesDisplayPanel.add(rawWindFixesTable); - mainPanel.add(createExpeditionWindImportPanel()); - mainPanel.add(createGribWindImportPanel()); - mainPanel.add(createNmeaWindImportPanel()); - mainPanel.add(createBravoWindImportPanel()); - mainPanel.add(createIgtimiWindImportPanel(mainPanel)); + + expeditionImportPanel = createExpeditionWindImportPanel(); + gribImportPanel = createGribWindImportPanel(); + nmeaImportPanel = createNmeaWindImportPanel(); + bravoImportPanel = createBravoWindImportPanel(); + igtimiImportPanel = igtimiImportPanel(mainPanel); + mainPanel.add(expeditionImportPanel); + mainPanel.add(gribImportPanel); + mainPanel.add(nmeaImportPanel); + mainPanel.add(bravoImportPanel); + mainPanel.add(igtimiImportPanel); + final Pair expeditionAllInOneRootAndImportPanel = createExpeditionAllInOneImportPanel(regattaRefresher); - mainPanel.add(expeditionAllInOneRootAndImportPanel.getA()); + expeditionAllInOneImporterPanel = expeditionAllInOneRootAndImportPanel.getA(); + mainPanel.add(expeditionAllInOneImporterPanel); containedRegattaDisplayers.add(expeditionAllInOneRootAndImportPanel.getB()); + updateVisibilityStateForPanels(); + + this.userService.addUserStatusEventHandler(new UserStatusEventHandler() { + @Override + public void onUserStatusChange(UserDTO user, boolean preAuthenticated) { + updateVisibilityStateForPanels(); + } + }); + // refresh regattas for this panel manually regattaRefresher.fillRegattas(); } + private void updateVisibilityStateForPanels() { + Set selectedRaces = refreshableRaceSelectionModel.getSelectedSet(); + if (selectedRaces.isEmpty()) { + // they could potentially hit all races, we don't have enough information to check here + expeditionImportPanel.setVisible(true); + gribImportPanel.setVisible(true); + nmeaImportPanel.setVisible(true); + bravoImportPanel.setVisible(true); + igtimiImportPanel.setVisible(true); + } else { + boolean canUpdateAll = true; + for (RaceDTO race : refreshableRaceSelectionModel.getSelectedSet()) { + if (!userService.hasPermission(race, DefaultActions.UPDATE)) { + canUpdateAll = false; + } + } + expeditionImportPanel.setVisible(canUpdateAll); + gribImportPanel.setVisible(canUpdateAll); + nmeaImportPanel.setVisible(canUpdateAll); + bravoImportPanel.setVisible(canUpdateAll); + igtimiImportPanel.setVisible(canUpdateAll); + } + + boolean canCreateEvent = userService.hasCurrentUserPermissionToCreateObjectOfType(SecuredDomainType.EVENT); + boolean canCreateRegatta = userService.hasCurrentUserPermissionToCreateObjectOfType(SecuredDomainType.REGATTA); + boolean canCreateRace = userService + .hasCurrentUserPermissionToCreateObjectOfType(SecuredDomainType.TRACKED_RACE); + boolean canCreateLeaderboard = userService + .hasCurrentUserPermissionToCreateObjectOfType(SecuredDomainType.LEADERBOARD); + expeditionAllInOneImporterPanel + .setVisible(canCreateEvent && canCreateLeaderboard && canCreateRace && canCreateRegatta); + } + + private CaptionPanel igtimiImportPanel(VerticalPanel mainPanel) { + return createIgtimiWindImportPanel(mainPanel); + } + private CaptionPanel createIgtimiWindImportPanel(VerticalPanel mainPanel) { CaptionPanel igtimiWindImportRootPanel = new CaptionPanel(stringMessages.igtimiWindImport()); VerticalPanel contentPanel = new VerticalPanel(); 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 8e34b5e75b0..5c836b551d5 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 @@ -6392,7 +6392,12 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S myTrackedRaces.add(trackedRace); } } else { - trackedRaces = getAllTrackedRaces(); + trackedRaces = new ArrayList<>(); + for (DynamicTrackedRace race : getAllTrackedRaces()) { + if (getSecurityService().hasCurrentUserUpdatePermission(race)) { + ((List) trackedRaces).add(race); + } + } } Map numberOfWindFixesImportedPerRace = new HashMap(); for (Account account : igtimiConnectionFactory.getAllAccounts()) { diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/windimport/AbstractWindImportServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/windimport/AbstractWindImportServlet.java index 61a3426e140..e02264c730c 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/windimport/AbstractWindImportServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/windimport/AbstractWindImportServlet.java @@ -19,6 +19,7 @@ import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; +import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.RegattaNameAndRaceName; import com.sap.sailing.server.gateway.SailingServerHttpServlet; import com.sap.sailing.server.gateway.windimport.AbstractWindImporter.UploadRequest; @@ -44,6 +45,9 @@ public abstract class AbstractWindImportServlet extends SailingServerHttpServlet WindImportResult windImportResult = new WindImportResult(); try { UploadRequest uploadRequest = readRequest(request); + for (RegattaAndRaceIdentifier trackedRace : uploadRequest.races) { + getSecurityService().checkCurrentUserUpdatePermission(trackedRace); + } importer.importWindForUploadRequest(getService(), windImportResult, uploadRequest); // Use text/html to prevent browsers from wrapping the response body, // see "Handling File Upload Responses in GWT" at http://www.artofsolving.com/node/50 diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/windimport/AbstractWindImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/windimport/AbstractWindImporter.java index d0a773f147a..fb8a85d5770 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/windimport/AbstractWindImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/windimport/AbstractWindImporter.java @@ -159,9 +159,6 @@ public abstract class AbstractWindImporter { public void importWindToWindSourceAndTrackedRaces(RacingEventService service, WindImportResult windImportResult, WindSource windSource, List trackedRaces, final Map streamsWithFilenames) throws IOException, InterruptedException, FormatNotSupportedException { - for (DynamicTrackedRace trackedRace : trackedRaces) { - service.getSecurityService().checkCurrentUserUpdatePermission(trackedRace); - } Iterable windFixes = importWind(streamsWithFilenames); if (!Util.isEmpty(windFixes)) { for (DynamicTrackedRace trackedRace : trackedRaces) { From 7e05cb02143eb0b39a9951ca45adca8087c92100 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Thu, 7 Mar 2019 18:09:03 +0100 Subject: [PATCH 10/26] fixed permission checks in BoatsResource and CompetitorsResource --- .../sap/sailing/server/gateway/jaxrs/api/BoatsResource.java | 4 +++- .../sailing/server/gateway/jaxrs/api/CompetitorsResource.java | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/BoatsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/BoatsResource.java index e56537f0b42..11cf40fc78c 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/BoatsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/BoatsResource.java @@ -14,6 +14,7 @@ import org.apache.commons.lang.StringEscapeUtils; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource; import com.sap.sailing.server.gateway.serialization.impl.BoatJsonSerializer; +import com.sap.sse.security.shared.impl.SecuredSecurityTypes; @Path("/v1/boats") public class BoatsResource extends AbstractSailingServerResource { @@ -32,7 +33,8 @@ public class BoatsResource extends AbstractSailingServerResource { } else { boolean skip = skipChecksDueToCorrectSecret(leaderboardName, regattaSecret); if (!skip) { - getSecurityService().checkCurrentUserReadPermission(boat); + getSecurityService().checkCurrentUserAnyExplicitPermissions(boat, + SecuredSecurityTypes.PublicReadableActions.READ_AND_READ_PUBLIC_ACTIONS); } BoatJsonSerializer boatJsonSerializer = BoatJsonSerializer.create(); String jsonString = boatJsonSerializer.serialize(boat).toJSONString(); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java index 3b24f4844de..7532f4523ec 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java @@ -39,6 +39,7 @@ import com.sap.sailing.server.gateway.serialization.impl.TeamJsonSerializer; import com.sap.sailing.server.interfaces.RacingEventService; import com.sap.sse.filestorage.InvalidPropertiesException; import com.sap.sse.filestorage.OperationFailedException; +import com.sap.sse.security.shared.impl.SecuredSecurityTypes; @Path("/v1/competitors") public class CompetitorsResource extends AbstractSailingServerResource { @@ -87,7 +88,8 @@ public class CompetitorsResource extends AbstractSailingServerResource { } else { boolean skip = skipChecksDueToCorrectSecret(leaderboardName, secret); if (!skip) { - getSecurityService().checkCurrentUserReadPermission(competitor); + getSecurityService().checkCurrentUserAnyExplicitPermissions(competitor, + SecuredSecurityTypes.PublicReadableActions.READ_AND_READ_PUBLIC_ACTIONS); } String jsonString = getCompetitorJSON(competitor).toJSONString(); response = Response.ok(jsonString).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8") From dacda84b834ea52571234155a4d411fbc0164898 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Thu, 7 Mar 2019 18:14:01 +0100 Subject: [PATCH 11/26] adjusted SailingViewerRole to no longer grant READ for competitor and boat. --- .../com/sap/sailing/server/security/SailingViewerRole.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/security/SailingViewerRole.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/security/SailingViewerRole.java index 916e4507a75..3873b0738c4 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/security/SailingViewerRole.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/security/SailingViewerRole.java @@ -20,9 +20,7 @@ public class SailingViewerRole extends RolePrototype { WildcardPermission.builder().withTypes(SecuredDomainType.EVENT, SecuredDomainType.LEADERBOARD_GROUP, SecuredDomainType.LEADERBOARD, SecuredDomainType.REGATTA, SecuredDomainType.TRACKED_RACE) .withActions(DefaultActions.READ).build(), WildcardPermission.builder().withTypes(SecuredDomainType.COMPETITOR, SecuredDomainType.BOAT) - .withActions(SecuredSecurityTypes.PublicReadableActions.READ_PUBLIC).build(), - WildcardPermission.builder().withTypes(SecuredDomainType.COMPETITOR, SecuredDomainType.BOAT) - .withActions(DefaultActions.READ).build()); + .withActions(SecuredSecurityTypes.PublicReadableActions.READ_PUBLIC).build()); } public static SailingViewerRole getInstance() { From c9a3c3652f1c1f6b284734c48f14d24c4059557f Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Thu, 7 Mar 2019 18:42:01 +0100 Subject: [PATCH 12/26] Bug 4919: added permission check for UPDATE permission for various leaderboard actions in the Leaderboards UI in the AdminConsole --- .../ui/adminconsole/LeaderboardConfigPanel.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java index 5f29264e6aa..1cabe07b874 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java @@ -317,7 +317,7 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel removeLeaderboard(leaderboardDTO); } }); - leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_EDIT_SCORES, leaderboardDTO -> { + leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_EDIT_SCORES, UPDATE, leaderboardDTO -> { String leaderboardEditingUrl = EntryPointWithSettingsLinkFactory .createLeaderboardEditingLink(leaderboardDTO.getName()); Window.open(leaderboardEditingUrl, "_blank", null); @@ -337,7 +337,8 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel }); editCompetitorsDialog.show(); }); - leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_CONFIGURE_URL, leaderboardDTO -> { + leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_CONFIGURE_URL, UPDATE, + leaderboardDTO -> { sailingService.getAvailableDetailTypesForLeaderboard(leaderboardDTO.getName(), null, new AsyncCallback>() { @@ -352,21 +353,21 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel } }); }); - leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_EXPORT_XML, + leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_EXPORT_XML, UPDATE, leaderboardDTO -> Window.open(UriUtils .fromString("/export/xml?domain=leaderboard&name=" + leaderboardDTO.getName()).asString(), "", null)); - leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_OPEN_COACH_DASHBOARD, + leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_OPEN_COACH_DASHBOARD, UPDATE, leaderboardDTO -> { Map dashboardURLParameters = new HashMap(); dashboardURLParameters.put("leaderboardName", leaderboardDTO.getName()); Window.open(EntryPointLinkFactory.createDashboardLink(dashboardURLParameters), "", null); }); - leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_SHOW_REGATTA_LOG, + leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_SHOW_REGATTA_LOG, UPDATE, leaderboardDTO -> showRegattaLog()); - leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_CREATE_PAIRINGLIST, + leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_CREATE_PAIRINGLIST, UPDATE, this::createPairingListTemplate); - leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_PRINT_PAIRINGLIST, + leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_PRINT_PAIRINGLIST, UPDATE, this::openPairingListEntryPoint); final DialogConfig config = EditOwnershipDialog.create( From 9ab4de92eff40d280148ca636e4a95ac4f825126 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Thu, 7 Mar 2019 19:31:00 +0100 Subject: [PATCH 13/26] TracTrac JSON documents split "url" field into "url_html" and "url_mobile" Change-Id: Ic91b83ba89cd373ca074171c9e6701575723f514 --- .../sailing/domain/tractracadapter/impl/JSONServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/JSONServiceImpl.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/JSONServiceImpl.java index 8ca0f20829c..5530e121910 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/JSONServiceImpl.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/JSONServiceImpl.java @@ -35,7 +35,7 @@ public class JSONServiceImpl implements JSONService { private RaceRecord createRaceRecord(URL jsonURL, boolean loadLiveAndStoredURI, JSONObject jsonRaceEntry) throws URISyntaxException, IOException { RaceRecord raceRecord = new RaceRecord(jsonURL, regattaName, - (String) jsonRaceEntry.get("name"), (String) jsonRaceEntry.get("url"), + (String) jsonRaceEntry.get("name"), (String) jsonRaceEntry.get("url_html"), (String) jsonRaceEntry.get("params_url"), (String) jsonRaceEntry.get("id"), (String) jsonRaceEntry.get("tracking_starttime"), From c756a4b456dd8b59932b1f76a01f8f753b58096a Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Fri, 8 Mar 2019 10:06:57 +0100 Subject: [PATCH 14/26] fixed permission check /user in REST API --- .../com/sap/sse/security/jaxrs/api/SecurityResource.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/SecurityResource.java b/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/SecurityResource.java index f1b18214a5e..bfc6f28e0ec 100644 --- a/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/SecurityResource.java +++ b/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/SecurityResource.java @@ -157,17 +157,17 @@ public class SecurityResource extends AbstractSecurityResource { final User user = getService().getUserByName(username == null ? subject.getPrincipal().toString() : username); if (user == null) { return Response.status(Status.PRECONDITION_FAILED).entity("User "+username+" not known").build(); - } else if (!(getService().hasCurrentUserReadPermission(user) && getService() - .hasCurrentUserAnyExplicitPermissions(user, SecuredSecurityTypes.PublicReadableActions.READ_PUBLIC))) { + } else if (getService().hasCurrentUserReadPermission(user) || getService() + .hasCurrentUserAnyExplicitPermissions(user, SecuredSecurityTypes.PublicReadableActions.READ_PUBLIC)) { // TODO: pruning when current user only has READ_PUBLIC - return Response.status(Status.UNAUTHORIZED).build(); - } else { JSONObject result = new JSONObject(); result.put("username", user.getName()); result.put("fullName", user.getFullName()); result.put("email", user.getEmail()); result.put("company", user.getCompany()); return Response.ok(result.toJSONString()).build(); + } else { + return Response.status(Status.UNAUTHORIZED).build(); } } From 21d9b36bb913ac92d5f68b7c8146123494cd041b Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Fri, 8 Mar 2019 10:51:00 +0100 Subject: [PATCH 15/26] Bug 4914: adjusted front end permissions --- .../gwt/ui/adminconsole/LeaderboardConfigPanel.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java index 1cabe07b874..6488c77b490 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java @@ -337,7 +337,7 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel }); editCompetitorsDialog.show(); }); - leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_CONFIGURE_URL, UPDATE, + leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_CONFIGURE_URL, READ, leaderboardDTO -> { sailingService.getAvailableDetailTypesForLeaderboard(leaderboardDTO.getName(), null, new AsyncCallback>() { @@ -353,21 +353,21 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel } }); }); - leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_EXPORT_XML, UPDATE, + leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_EXPORT_XML, READ, leaderboardDTO -> Window.open(UriUtils .fromString("/export/xml?domain=leaderboard&name=" + leaderboardDTO.getName()).asString(), "", null)); - leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_OPEN_COACH_DASHBOARD, UPDATE, + leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_OPEN_COACH_DASHBOARD, READ, leaderboardDTO -> { Map dashboardURLParameters = new HashMap(); dashboardURLParameters.put("leaderboardName", leaderboardDTO.getName()); Window.open(EntryPointLinkFactory.createDashboardLink(dashboardURLParameters), "", null); }); - leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_SHOW_REGATTA_LOG, UPDATE, + leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_SHOW_REGATTA_LOG, READ, leaderboardDTO -> showRegattaLog()); leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_CREATE_PAIRINGLIST, UPDATE, this::createPairingListTemplate); - leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_PRINT_PAIRINGLIST, UPDATE, + leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_PRINT_PAIRINGLIST, READ, this::openPairingListEntryPoint); final DialogConfig config = EditOwnershipDialog.create( From 96a8f24c526dfa62cbbf7407763041fb669a6396 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Fri, 8 Mar 2019 12:42:37 +0100 Subject: [PATCH 16/26] Bug 4914: secured XmlExport endpoint in back end for Leaderboards with READ permission --- java/com.sap.sailing.xmlexport/META-INF/MANIFEST.MF | 3 ++- .../src/com/sap/sailing/xmlexport/ExportAction.java | 11 +++++++++-- .../com/sap/sailing/xmlexport/LeaderboardData.java | 8 +++++--- .../com/sap/sailing/xmlexport/XmlExportServlet.java | 3 ++- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/java/com.sap.sailing.xmlexport/META-INF/MANIFEST.MF b/java/com.sap.sailing.xmlexport/META-INF/MANIFEST.MF index c3b14e2e719..b3f3cdb6dac 100644 --- a/java/com.sap.sailing.xmlexport/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.xmlexport/META-INF/MANIFEST.MF @@ -18,7 +18,8 @@ Require-Bundle: com.sap.sailing.server, com.sap.sse.common, com.sap.sse.replication, org.jdom;bundle-version="1.1.1", - com.sap.sailing.server.interface + com.sap.sailing.server.interface, + com.sap.sse.security Bundle-ClassPath: . Web-ContextPath: /export Automatic-Module-Name: com.sap.sailing.xmlexport diff --git a/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/ExportAction.java b/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/ExportAction.java index 3156508c51b..3073cd77c58 100644 --- a/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/ExportAction.java +++ b/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/ExportAction.java @@ -35,6 +35,7 @@ import com.sap.sse.common.Speed; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; import com.sap.sse.common.Util.Triple; +import com.sap.sse.security.SecurityService; public abstract class ExportAction { private HttpServletRequest req; @@ -44,11 +45,14 @@ public abstract class ExportAction { private Leaderboard leaderboard; protected final boolean useProvidedLeaderboard; private String resultingXMLData; + private final SecurityService securityService; - public ExportAction(HttpServletRequest req, HttpServletResponse res, RacingEventService service) { + public ExportAction(HttpServletRequest req, HttpServletResponse res, RacingEventService service, + final SecurityService securityService) { this.req = req; this.res = res; this.service = service; + this.securityService = securityService; this.leaderboard = null; this.useProvidedLeaderboard = false; } @@ -56,6 +60,8 @@ public abstract class ExportAction { public ExportAction(Leaderboard leaderboard) { this.leaderboard = leaderboard; this.useProvidedLeaderboard = true; + // no permission check needed since we already got a leaderboard + this.securityService = null; } public String getAttribute(String name) { @@ -76,7 +82,8 @@ public abstract class ExportAction { if (leaderboardName == null) { throw new ServletException("Use the name= parameter to specify the leaderboard"); } - leaderboard = getService().getLeaderboardByName(leaderboardName); + leaderboard = getService().getLeaderboardByName(leaderboardName); + securityService.checkCurrentUserReadPermission(leaderboard); if (leaderboard == null) { throw new ServletException("Leaderboard " + leaderboardName + " not found."); } diff --git a/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/LeaderboardData.java b/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/LeaderboardData.java index 0e6e6014b08..c4ca9278d47 100644 --- a/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/LeaderboardData.java +++ b/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/LeaderboardData.java @@ -61,6 +61,7 @@ import com.sap.sse.common.Util; import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsDurationImpl; import com.sap.sse.common.impl.MillisecondsTimePoint; +import com.sap.sse.security.SecurityService; /** * Exports all data from a leaderboard into XML format. @@ -81,9 +82,10 @@ public class LeaderboardData extends ExportAction { private static final String VERY_STRONG_WIND_DESCRIPTION = "Very Strong"; private final Map> raceColumnToCompetitors; - - public LeaderboardData(HttpServletRequest req, HttpServletResponse res, RacingEventService service) { - super(req, res, service); + + public LeaderboardData(HttpServletRequest req, HttpServletResponse res, RacingEventService service, + final SecurityService securityService) { + super(req, res, service, securityService); this.raceColumnToCompetitors = new HashMap<>(); } diff --git a/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/XmlExportServlet.java b/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/XmlExportServlet.java index 9ecec4bd6ee..08ce221f6d8 100755 --- a/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/XmlExportServlet.java +++ b/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/XmlExportServlet.java @@ -17,7 +17,8 @@ public class XmlExportServlet extends SailingServerHttpServlet { try { if ((action != null) && !"".equals(action)) { if ("leaderboard".equalsIgnoreCase(action)) { - final LeaderboardData leaderboardData = new LeaderboardData(req, res, getService()); + final LeaderboardData leaderboardData = new LeaderboardData(req, res, getService(), + getSecurityService()); leaderboardData.perform(); return; } else if ("foiling".equalsIgnoreCase(action)) { From 6a62c86fae3547fae2ea340203e787cf6ae28535 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Fri, 8 Mar 2019 12:43:11 +0100 Subject: [PATCH 17/26] Bug 4914: secured xml export endpoint in back end for foiling data with READ permission --- .../src/com/sap/sailing/xmlexport/FoilingData.java | 7 ++++++- .../src/com/sap/sailing/xmlexport/XmlExportServlet.java | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/FoilingData.java b/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/FoilingData.java index 1ee8614f952..b4a7e2778d9 100644 --- a/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/FoilingData.java +++ b/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/FoilingData.java @@ -33,6 +33,7 @@ import com.sap.sailing.server.interfaces.RacingEventService; import com.sap.sse.common.Bearing; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; +import com.sap.sse.security.SecurityService; public class FoilingData { @@ -40,12 +41,15 @@ public class FoilingData { private final HttpServletResponse res; private final RacingEventService service; private final boolean useProvidedLeaderboard; + private SecurityService securityService; - public FoilingData(HttpServletRequest req, HttpServletResponse res, RacingEventService service) { + public FoilingData(HttpServletRequest req, HttpServletResponse res, RacingEventService service, + final SecurityService securityService) { this.req = req; this.res = res; this.service = service; this.useProvidedLeaderboard = false; + this.securityService = securityService; } public String getAttribute(String name) { @@ -64,6 +68,7 @@ public class FoilingData { throw new ServletException("Use the name= parameter to specify the leaderboard"); } leaderboard = getService().getLeaderboardByName(leaderboardName); + securityService.checkCurrentUserReadPermission(leaderboard); if (leaderboard == null) { throw new ServletException("Leaderboard " + leaderboardName + " not found."); } diff --git a/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/XmlExportServlet.java b/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/XmlExportServlet.java index 08ce221f6d8..e58bf9d62fc 100755 --- a/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/XmlExportServlet.java +++ b/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/XmlExportServlet.java @@ -22,7 +22,7 @@ public class XmlExportServlet extends SailingServerHttpServlet { leaderboardData.perform(); return; } else if ("foiling".equalsIgnoreCase(action)) { - final FoilingData foilingData = new FoilingData(req, res, getService()); + final FoilingData foilingData = new FoilingData(req, res, getService(), getSecurityService()); foilingData.perform(); return; } From 07e94b7c1c74d149db2739a5c883aad03fc56525 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Fri, 8 Mar 2019 13:05:24 +0100 Subject: [PATCH 18/26] Bug 4914: secured backend endpoint to retrieve regatta log --- .../java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java | 3 +++ 1 file changed, 3 insertions(+) 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 d80a7713c5f..2a745373344 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 @@ -5513,6 +5513,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public RegattaLogDTO getRegattaLog(String leaderboardName) throws DoesNotHaveRegattaLogException { RegattaLogDTO result = null; + Leaderboard l = getService().getLeaderboardByName(leaderboardName); + getSecurityService().checkCurrentUserReadPermission(l); + RegattaLog regattaLog = getRegattaLogInternal(leaderboardName); if (regattaLog != null) { List entries = new ArrayList<>(); From 31f2321f1ba4690d8c74f2643d1243097de84148 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Fri, 8 Mar 2019 15:37:30 +0100 Subject: [PATCH 19/26] Bug 4894: added permission check for leaderboard update for AddEntryToRaceLogJsonPostServlet --- .../gateway/impl/rc/AddEntryToRaceLogJsonPostServlet.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/AddEntryToRaceLogJsonPostServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/AddEntryToRaceLogJsonPostServlet.java index 2734a8abd8f..4f734d7facd 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/AddEntryToRaceLogJsonPostServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/AddEntryToRaceLogJsonPostServlet.java @@ -13,6 +13,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringEscapeUtils; +import org.apache.shiro.SecurityUtils; import org.json.simple.JSONObject; import org.json.simple.JSONValue; import org.json.simple.parser.ParseException; @@ -36,6 +37,7 @@ import com.sap.sailing.server.gateway.serialization.racelog.tracking.DeviceIdent import com.sap.sailing.server.gateway.serialization.racelog.tracking.impl.PlaceHolderDeviceIdentifierJsonHandler; import com.sap.sailing.server.interfaces.RacingEventService; import com.sap.sse.common.TypeBasedServiceFinder; +import com.sap.sse.security.shared.HasPermissions.DefaultActions; public class AddEntryToRaceLogJsonPostServlet extends AbstractJsonHttpServlet { private static final long serialVersionUID = 7704668926551060433L; @@ -69,7 +71,6 @@ public class AddEntryToRaceLogJsonPostServlet extends AbstractJsonHttpServlet { String.format("Missing parameter '%s'.", RaceLogServletConstants.PARAMS_LEADERBOARD_NAME)); return; } - //SecurityUtils.getSubject().checkPermission(SecuredDomainType.LEADERBOARD.getStringPermissionForObjects(DefaultActions.UPDATE, leaderboardName)); String raceColumnName = request.getParameter(RaceLogServletConstants.PARAMS_RACE_COLUMN_NAME); if (raceColumnName == null) { @@ -93,6 +94,8 @@ public class AddEntryToRaceLogJsonPostServlet extends AbstractJsonHttpServlet { response.sendError(HttpServletResponse.SC_NOT_FOUND, "Leaderboard "+StringEscapeUtils.escapeHtml(leaderboardName)+" not found."); return; } + SecurityUtils.getSubject() + .checkPermission(leaderboard.getIdentifier().getStringPermission(DefaultActions.UPDATE)); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); if (raceColumn == null) { From dc6633cbcc21bef1d817b55287bb558e3981985d Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Fri, 8 Mar 2019 15:42:01 +0100 Subject: [PATCH 20/26] Bug 4894: added permission checks for leaderboard read and tracked race read permissions in CompetitorsAndBoatsJsonExportServlet --- .../rc/CompetitorsAndBoatsJsonExportServlet.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/CompetitorsAndBoatsJsonExportServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/CompetitorsAndBoatsJsonExportServlet.java index d20f911b5ba..6ce508ee463 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/CompetitorsAndBoatsJsonExportServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/CompetitorsAndBoatsJsonExportServlet.java @@ -6,6 +6,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.shiro.SecurityUtils; import org.json.simple.JSONArray; import org.json.simple.JSONObject; @@ -15,10 +16,12 @@ import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.common.racelog.RaceLogServletConstants; import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.server.gateway.AbstractJsonHttpServlet; import com.sap.sailing.server.gateway.serialization.impl.CompetitorAndBoatJsonSerializer; import com.sap.sailing.server.interfaces.RacingEventService; import com.sap.sse.common.Util.Pair; +import com.sap.sse.security.shared.HasPermissions.DefaultActions; public class CompetitorsAndBoatsJsonExportServlet extends AbstractJsonHttpServlet { private static final long serialVersionUID = 4510175441769759252L; @@ -49,6 +52,10 @@ public class CompetitorsAndBoatsJsonExportServlet extends AbstractJsonHttpServle response.sendError(HttpServletResponse.SC_NOT_FOUND, "No such leaderboard found."); return; } + + SecurityUtils.getSubject() + .checkPermission(leaderboard.getIdentifier().getStringPermission(DefaultActions.READ)); + RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); if (raceColumn == null) { response.sendError(HttpServletResponse.SC_NOT_FOUND, "No such race column found."); @@ -61,6 +68,13 @@ public class CompetitorsAndBoatsJsonExportServlet extends AbstractJsonHttpServle } CompetitorAndBoatJsonSerializer competitorsAndBoatsSerializer = CompetitorAndBoatJsonSerializer.create(); JSONArray result = new JSONArray(); + final TrackedRace trackedRace = raceColumn.getTrackedRace(fleet); + + if (trackedRace != null) { + SecurityUtils.getSubject() + .checkPermission(trackedRace.getIdentifier().getStringPermission(DefaultActions.READ)); + } + for (Competitor competitor : leaderboard.getCompetitors(raceColumn, fleet)) { Boat boat = leaderboard.getBoatOfCompetitor(competitor, raceColumn, fleet); JSONObject serializeCompetitorAndBoat = competitorsAndBoatsSerializer.serialize(new Pair(competitor, boat)); From 6fe2dbe6cbf6fa07d6fbe076b53cb205d6a85bdd Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Fri, 8 Mar 2019 15:42:54 +0100 Subject: [PATCH 21/26] Bug 4894: added permission check for leaderboard read in CompetitorsJsonExportServlet --- .../server/gateway/impl/rc/CompetitorsJsonExportServlet.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/CompetitorsJsonExportServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/CompetitorsJsonExportServlet.java index 3328fc56ecc..3b5ddc7808c 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/CompetitorsJsonExportServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/CompetitorsJsonExportServlet.java @@ -6,6 +6,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.shiro.SecurityUtils; import org.json.simple.JSONArray; import com.sap.sailing.domain.base.Competitor; @@ -16,6 +17,7 @@ import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.server.gateway.AbstractJsonHttpServlet; import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; import com.sap.sailing.server.interfaces.RacingEventService; +import com.sap.sse.security.shared.HasPermissions.DefaultActions; public class CompetitorsJsonExportServlet extends AbstractJsonHttpServlet { private static final long serialVersionUID = 4510175441769759252L; @@ -46,6 +48,9 @@ public class CompetitorsJsonExportServlet extends AbstractJsonHttpServlet { response.sendError(HttpServletResponse.SC_NOT_FOUND, "No such leaderboard found."); return; } + SecurityUtils.getSubject() + .checkPermission(leaderboard.getIdentifier().getStringPermission(DefaultActions.READ)); + RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); if (raceColumn == null) { response.sendError(HttpServletResponse.SC_NOT_FOUND, "No such race column found."); From 5e979c289325bf208b301dd2d52c639b587639d2 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Fri, 8 Mar 2019 15:44:31 +0100 Subject: [PATCH 22/26] Bug 4894: added permission checks for leaderboard read and trackedrace read permissions in CourseJsonExportServlet --- .../server/gateway/impl/rc/CourseJsonExportServlet.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/CourseJsonExportServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/CourseJsonExportServlet.java index 50800b23917..00bb8874819 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/CourseJsonExportServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/CourseJsonExportServlet.java @@ -6,6 +6,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.shiro.SecurityUtils; import org.json.simple.JSONObject; import com.sap.sailing.domain.base.Course; @@ -21,6 +22,7 @@ import com.sap.sailing.server.gateway.serialization.coursedata.impl.GateJsonSeri import com.sap.sailing.server.gateway.serialization.coursedata.impl.MarkJsonSerializer; import com.sap.sailing.server.gateway.serialization.coursedata.impl.WaypointJsonSerializer; import com.sap.sailing.server.interfaces.RacingEventService; +import com.sap.sse.security.shared.HasPermissions.DefaultActions; public class CourseJsonExportServlet extends AbstractJsonHttpServlet { @@ -52,6 +54,9 @@ public class CourseJsonExportServlet extends AbstractJsonHttpServlet { response.sendError(HttpServletResponse.SC_NOT_FOUND, "No such leaderboard found."); return; } + SecurityUtils.getSubject() + .checkPermission(leaderboard.getIdentifier().getStringPermission(DefaultActions.READ)); + RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); if (raceColumn == null) { response.sendError(HttpServletResponse.SC_NOT_FOUND, "No such race column found."); @@ -65,6 +70,8 @@ public class CourseJsonExportServlet extends AbstractJsonHttpServlet { TrackedRace trackedRace = raceColumn.getTrackedRace(fleet); JSONObject result; if (trackedRace != null) { + SecurityUtils.getSubject() + .checkPermission(trackedRace.getIdentifier().getStringPermission(DefaultActions.READ)); Course course = raceColumn.getRaceDefinition(fleet).getCourse(); CourseBaseJsonSerializer serializer = new CourseBaseJsonSerializer( new WaypointJsonSerializer( From e55b8f0d7345748fdc64ad371a2172613e77dcf3 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Fri, 8 Mar 2019 15:45:31 +0100 Subject: [PATCH 23/26] Bug 4894: added permission checks for leaderboard read and trackedrace read permissions in MarkPositionsJsonExportServlet --- .../gateway/impl/rc/MarkPositionsJsonExportServlet.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/MarkPositionsJsonExportServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/MarkPositionsJsonExportServlet.java index 9c341d8d40f..f01a694c676 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/MarkPositionsJsonExportServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/MarkPositionsJsonExportServlet.java @@ -7,6 +7,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.shiro.SecurityUtils; import org.json.simple.JSONArray; import com.sap.sailing.domain.base.Fleet; @@ -24,6 +25,7 @@ import com.sap.sailing.server.interfaces.RacingEventService; import com.sap.sse.common.Distance; import com.sap.sse.common.Util; import com.sap.sse.common.impl.MillisecondsTimePoint; +import com.sap.sse.security.shared.HasPermissions.DefaultActions; public class MarkPositionsJsonExportServlet extends AbstractJsonHttpServlet { @@ -31,7 +33,6 @@ public class MarkPositionsJsonExportServlet extends AbstractJsonHttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - String leaderboardName = request.getParameter(RaceLogServletConstants.PARAMS_LEADERBOARD_NAME); if (leaderboardName == null) { response.sendError(HttpServletResponse.SC_BAD_REQUEST, @@ -60,6 +61,8 @@ public class MarkPositionsJsonExportServlet extends AbstractJsonHttpServlet { response.sendError(HttpServletResponse.SC_NOT_FOUND, "No such leaderboard found."); return; } + SecurityUtils.getSubject() + .checkPermission(leaderboard.getIdentifier().getStringPermission(DefaultActions.READ)); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); if (raceColumn == null) { @@ -78,6 +81,9 @@ public class MarkPositionsJsonExportServlet extends AbstractJsonHttpServlet { JSONArray result = new JSONArray(); if (trackedRace != null) { + SecurityUtils.getSubject() + .checkPermission(trackedRace.getIdentifier().getStringPermission(DefaultActions.UPDATE)); + MarkJsonSerializer markSerializer = new MarkJsonSerializer(); PositionJsonSerializer positionSerializer = new PositionJsonSerializer(); PositionedMarkJsonSerializer positionedMarkSerializer = new PositionedMarkJsonSerializer(markSerializer, positionSerializer); From c875028cf9f9d824d4d9b952351fd429a0e9b27f Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Fri, 8 Mar 2019 15:47:21 +0100 Subject: [PATCH 24/26] Bug 4894: added permission checks for leaderboard read and regatta read in RaceGroupJsonExportServlet --- .../gateway/impl/rc/RaceGroupJsonExportServlet.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/RaceGroupJsonExportServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/RaceGroupJsonExportServlet.java index 0e859d03356..da6d0625456 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/RaceGroupJsonExportServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/RaceGroupJsonExportServlet.java @@ -9,6 +9,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.shiro.SecurityUtils; import org.json.simple.JSONArray; import com.sap.sailing.domain.abstractlog.race.RaceLog; @@ -39,6 +40,7 @@ import com.sap.sailing.server.gateway.serialization.racegroup.impl.SeriesWithRow import com.sap.sailing.server.gateway.serialization.racegroup.impl.SeriesWithRowsOfRaceGroupSerializer; import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogEventSerializer; import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogSerializer; +import com.sap.sse.security.shared.HasPermissions.DefaultActions; public class RaceGroupJsonExportServlet extends AbstractJsonHttpServlet { private static final long serialVersionUID = 4510175441769759252L; @@ -73,9 +75,16 @@ public class RaceGroupJsonExportServlet extends AbstractJsonHttpServlet { final Set regattasForWhichRegattaLeaderboardsWereAdded = new HashSet<>(); for (Leaderboard leaderboard : getService().getLeaderboards().values()) { if (filterCourseArea.equals(leaderboard.getDefaultCourseArea())) { + SecurityUtils.getSubject() + .checkPermission(leaderboard.getIdentifier().getStringPermission(DefaultActions.READ)); if (leaderboard instanceof RegattaLeaderboard && !(leaderboard instanceof RegattaLeaderboardWithEliminations)) { result.add(serializer.serialize(raceGroupFactory.convert((RegattaLeaderboard) leaderboard))); - regattasForWhichRegattaLeaderboardsWereAdded.add(((RegattaLeaderboard) leaderboard).getRegatta()); + + final Regatta regatta = ((RegattaLeaderboard) leaderboard).getRegatta(); + SecurityUtils.getSubject() + .checkPermission(regatta.getIdentifier().getStringPermission(DefaultActions.READ)); + + regattasForWhichRegattaLeaderboardsWereAdded.add(regatta); } else if (leaderboard instanceof FlexibleLeaderboard) { result.add(serializer.serialize(raceGroupFactory.convert((FlexibleLeaderboard) leaderboard))); } From e8165fa359bc0f2f1522f15f76732a57b43c502f Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Fri, 8 Mar 2019 15:51:32 +0100 Subject: [PATCH 25/26] Bug 4894: changed permission check from trackedrace update to trackedrace read in MarkPositionsJsonExportServlet --- .../server/gateway/impl/rc/MarkPositionsJsonExportServlet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/MarkPositionsJsonExportServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/MarkPositionsJsonExportServlet.java index f01a694c676..4074843293e 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/MarkPositionsJsonExportServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/MarkPositionsJsonExportServlet.java @@ -82,7 +82,7 @@ public class MarkPositionsJsonExportServlet extends AbstractJsonHttpServlet { if (trackedRace != null) { SecurityUtils.getSubject() - .checkPermission(trackedRace.getIdentifier().getStringPermission(DefaultActions.UPDATE)); + .checkPermission(trackedRace.getIdentifier().getStringPermission(DefaultActions.READ)); MarkJsonSerializer markSerializer = new MarkJsonSerializer(); PositionJsonSerializer positionSerializer = new PositionJsonSerializer(); From aa02ce9bc4e30ee14f3258988638c87cdc25d482 Mon Sep 17 00:00:00 2001 From: Steffen Jacobs Date: Fri, 8 Mar 2019 15:57:02 +0100 Subject: [PATCH 26/26] Bug 4894: added permission check for trackedrace update in AbstractWindImporter --- .../gateway/windimport/AbstractWindImporter.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/windimport/AbstractWindImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/windimport/AbstractWindImporter.java index fb8a85d5770..5e4ec432352 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/windimport/AbstractWindImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/windimport/AbstractWindImporter.java @@ -9,6 +9,7 @@ import java.util.List; import java.util.Map; import org.apache.commons.fileupload.FileItem; +import org.apache.shiro.SecurityUtils; import org.json.simple.JSONArray; import org.json.simple.JSONObject; @@ -22,6 +23,7 @@ import com.sap.sailing.domain.tracking.DynamicTrackedRace; import com.sap.sailing.server.gateway.windimport.AbstractWindImporter.WindImportResult.RaceEntry; import com.sap.sailing.server.interfaces.RacingEventService; import com.sap.sse.common.Util; +import com.sap.sse.security.shared.HasPermissions.DefaultActions; public abstract class AbstractWindImporter { public static class UploadRequest { @@ -138,6 +140,8 @@ public abstract class AbstractWindImporter { if (uploadRequest.races.size() > 0) { for (RegattaAndRaceIdentifier raceEntry : uploadRequest.races) { DynamicTrackedRace trackedRace = service.getTrackedRace(raceEntry); + SecurityUtils.getSubject() + .checkPermission(trackedRace.getIdentifier().getStringPermission(DefaultActions.UPDATE)); if (trackedRace != null) { trackedRaces.add(trackedRace); } @@ -145,7 +149,11 @@ public abstract class AbstractWindImporter { } else { for (Regatta regatta : service.getAllRegattas()) { for (RaceDefinition raceDefinition : regatta.getAllRaces()) { - trackedRaces.add(service.getTrackedRegatta(regatta).getTrackedRace(raceDefinition)); + final DynamicTrackedRace trackedRace = service.getTrackedRegatta(regatta).getTrackedRace(raceDefinition); + if (SecurityUtils.getSubject() + .isPermitted(trackedRace.getIdentifier().getStringPermission(DefaultActions.UPDATE))) { + trackedRaces.add(trackedRace); + } } } }