Merge remote-tracking branch 'origin/permission-vertical' into bug4895

This commit is contained in:
Steffen Jacobs committed 2019-03-07 15:34:07 +01:00
commit 82528c5634
20 files changed
+167 -95

No files matched your search

@@ -598,7 +598,6 @@ import com.sap.sse.replication.Replicable;
import com.sap.sse.replication.ReplicationMasterDescriptor;
import com.sap.sse.replication.ReplicationService;
import com.sap.sse.security.Action;
import com.sap.sse.security.ActionWithResult;
import com.sap.sse.security.SecurityService;
import com.sap.sse.security.shared.HasPermissions;
import com.sap.sse.security.shared.HasPermissions.DefaultActions;
@@ -1859,6 +1858,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
public void setWind(RegattaAndRaceIdentifier raceIdentifier, WindDTO windDTO) {
DynamicTrackedRace trackedRace = (DynamicTrackedRace) getExistingTrackedRace(raceIdentifier);
if (trackedRace != null) {
getSecurityService().checkCurrentUserUpdatePermission(trackedRace);
Position p = null;
if (windDTO.position != null) {
p = windDTO.position;
@@ -2541,16 +2541,19 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
@Override
public void setRaceIsKnownToStartUpwind(RegattaAndRaceIdentifier raceIdentifier, boolean raceIsKnownToStartUpwind) {
getSecurityService().checkCurrentUserUpdatePermission(raceIdentifier);
getService().apply(new SetRaceIsKnownToStartUpwind(raceIdentifier, raceIsKnownToStartUpwind));
}
@Override
public void setWindSourcesToExclude(RegattaAndRaceIdentifier raceIdentifier, Iterable<WindSource> windSourcesToExclude) {
getSecurityService().checkCurrentUserUpdatePermission(raceIdentifier);
getService().apply(new SetWindSourcesToExclude(raceIdentifier, windSourcesToExclude));
}
@Override
public WindInfoForRaceDTO getWindSourcesInfo(RegattaAndRaceIdentifier raceIdentifier) {
getSecurityService().checkCurrentUserReadPermission(raceIdentifier);
WindInfoForRaceDTO result = null;
TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier);
if (trackedRace != null) {
@@ -2576,6 +2579,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
public void removeWind(RegattaAndRaceIdentifier raceIdentifier, WindDTO windDTO) {
DynamicTrackedRace trackedRace = (DynamicTrackedRace) getExistingTrackedRace(raceIdentifier);
if (trackedRace != null) {
getSecurityService().checkCurrentUserUpdatePermission(trackedRace);
Position p = null;
if (windDTO.position != null) {
p = windDTO.position;
@@ -2657,9 +2661,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
UUID courseAreaId) {
return getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
SecuredDomainType.LEADERBOARD, Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName),
leaderboardDisplayName, new ActionWithResult<StrippedLeaderboardDTOWithSecurity>() {
leaderboardDisplayName, new Callable<StrippedLeaderboardDTOWithSecurity>() {
@Override
public StrippedLeaderboardDTOWithSecurity run() throws Exception {
public StrippedLeaderboardDTOWithSecurity call() throws Exception {
return createStrippedLeaderboardDTOWithSecurity(
getService().apply(new CreateFlexibleLeaderboard(leaderboardName,
leaderboardDisplayName, discardThresholds,
@@ -2674,9 +2678,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
int[] discardThresholds) {
return getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
SecuredDomainType.LEADERBOARD, Leaderboard.getTypeRelativeObjectIdentifier(regattaIdentifier), leaderboardDisplayName,
new ActionWithResult<StrippedLeaderboardDTOWithSecurity>() {
new Callable<StrippedLeaderboardDTOWithSecurity>() {
@Override
public StrippedLeaderboardDTOWithSecurity run() throws Exception {
public StrippedLeaderboardDTOWithSecurity call() throws Exception {
return createStrippedLeaderboardDTOWithSecurity(getService().apply(new CreateRegattaLeaderboard(
regattaIdentifier, leaderboardDisplayName, discardThresholds)), false, false);
}
@@ -2689,9 +2693,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
String fullRegattaLeaderboardName) {
return getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
SecuredDomainType.LEADERBOARD, Leaderboard.getTypeRelativeObjectIdentifier(name), displayName,
new ActionWithResult<StrippedLeaderboardDTOWithSecurity>() {
new Callable<StrippedLeaderboardDTOWithSecurity>() {
@Override
public StrippedLeaderboardDTOWithSecurity run() throws Exception {
public StrippedLeaderboardDTOWithSecurity call() throws Exception {
return createStrippedLeaderboardDTOWithSecurity(
getService().apply(new CreateRegattaLeaderboardWithEliminations(name, displayName,
fullRegattaLeaderboardName)),
@@ -4106,9 +4110,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
UUID newLeaderboardGroupId = UUID.randomUUID();
return getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
SecuredDomainType.LEADERBOARD_GROUP, LeaderboardGroupImpl.getTypeRelativeObjectIdentifier(newLeaderboardGroupId),
displayName, new ActionWithResult<LeaderboardGroupDTO>() {
displayName, new Callable<LeaderboardGroupDTO>() {
@Override
public LeaderboardGroupDTO run() throws Exception {
public LeaderboardGroupDTO call() throws Exception {
CreateLeaderboardGroup createLeaderboardGroupOp = new CreateLeaderboardGroup(
newLeaderboardGroupId, groupName, description, displayName, displayGroupsInReverseOrder,
leaderBoards, overallLeaderboardDiscardThresholds,
@@ -4296,9 +4300,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
return getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
SecuredDomainType.EVENT, EventBaseImpl.getTypeRelativeObjectIdentifier(eventUuid),
eventName, new ActionWithResult<EventDTO>() {
eventName, new Callable<EventDTO>() {
@Override
public EventDTO run() throws Exception {
public EventDTO call() throws Exception {
TimePoint startTimePoint = startDate != null ? new MillisecondsTimePoint(startDate) : null;
TimePoint endTimePoint = endDate != null ? new MillisecondsTimePoint(endDate) : null;
URL officialWebsiteURL = officialWebsiteURLAsString != null
@@ -4864,10 +4868,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
return getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
SecuredDomainType.REGATTA, Regatta.getTypeRelativeObjectIdentifier(regattaName),
regattaName, new ActionWithResult<RegattaDTO>() {
regattaName, new Callable<RegattaDTO>() {
@Override
public RegattaDTO run() throws Exception {
public RegattaDTO call() throws Exception {
TimePoint startTimePoint = startDate != null ? new MillisecondsTimePoint(startDate) : null;
TimePoint endTimePoint = endDate != null ? new MillisecondsTimePoint(endDate) : null;
Regatta regatta = getService().apply(new AddSpecificRegatta(regattaName, boatClassName,
@@ -4996,10 +5000,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
});
} else {
getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(qualifiedTypeIdentifier,
new ActionWithResult<Void>() {
new Callable<Void>() {
@Override
public Void run() throws Exception {
public Void call() throws Exception {
getSecurityService().removePermissionFromUser(allUser.getName(),
createObjectOnCurrentServerPermission);
return null;
@@ -5815,9 +5819,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
final DynamicBoat boat = (DynamicBoat) addOrUpdateBoatInternal(competitor.getBoat());
result = getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
SecuredDomainType.COMPETITOR, CompetitorImpl.getTypeRelativeObjectIdentifier(competitorUUID),
competitor.getName(), new ActionWithResult<CompetitorWithBoat>() {
competitor.getName(), new Callable<CompetitorWithBoat>() {
@Override
public CompetitorWithBoat run() throws Exception {
public CompetitorWithBoat call() throws Exception {
return getBaseDomainFactory().getCompetitorAndBoatStore().getOrCreateCompetitorWithBoat(
competitorUUID, competitor.getName(), competitor.getShortName(),
competitor.getColor(), competitor.getEmail(),
@@ -5859,10 +5863,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
DynamicTeam team = new TeamImpl(competitor.getName() + " team", Collections.singleton(sailor), null);
result = getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
SecuredDomainType.COMPETITOR, CompetitorImpl.getTypeRelativeObjectIdentifier(competitorUUID),
competitor.getName(), new ActionWithResult<Competitor>() {
competitor.getName(), new Callable<Competitor>() {
@Override
public Competitor run() throws Exception {
public Competitor call() throws Exception {
return getBaseDomainFactory().getOrCreateCompetitor(competitorUUID, competitor.getName(),
competitor.getShortName(), competitor.getColor(), competitor.getEmail(),
competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()),
@@ -5948,10 +5952,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
UUID boatUUID = UUID.randomUUID();
BoatClass boatClass = getBaseDomainFactory().getOrCreateBoatClass(boat.getBoatClass().getName());
result = getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
SecuredDomainType.BOAT, BoatImpl.getTypeRelativeObjectIdentifier(boatUUID), boat.getName(), new ActionWithResult<Boat>() {
SecuredDomainType.BOAT, BoatImpl.getTypeRelativeObjectIdentifier(boatUUID), boat.getName(), new Callable<Boat>() {
@Override
public Boat run() throws Exception {
public Boat call() throws Exception {
return getBaseDomainFactory().getOrCreateBoat(boatUUID, boat.getName(), boatClass,
boat.getSailId(), boat.getColor());
}
@@ -8014,9 +8018,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
public void removeExpeditionDeviceConfiguration(ExpeditionDeviceConfiguration deviceConfiguration) {
QualifiedObjectIdentifier identifier = deviceConfiguration.getType().getQualifiedObjectIdentifier(deviceConfiguration.getTypeRelativeObjectIdentifier(ServerInfo.getName()));
getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(identifier,
new ActionWithResult<Void>() {
new Callable<Void>() {
@Override
public Void run() throws Exception {
public Void call() throws Exception {
// TODO consider replication
final ExpeditionTrackerFactory expeditionConnector = expeditionConnectorTracker.getService();
if (expeditionConnector != null) {
@@ -11,6 +11,7 @@ import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Callable;
import javax.ws.rs.core.Response;
@@ -39,7 +40,6 @@ import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.mongodb.MongoDBConfiguration;
import com.sap.sse.mongodb.MongoDBService;
import com.sap.sse.security.Action;
import com.sap.sse.security.ActionWithResult;
import com.sap.sse.security.SecurityService;
import com.sap.sse.security.shared.OwnershipAnnotation;
import com.sap.sse.security.shared.WithQualifiedObjectIdentifier;
@@ -81,7 +81,7 @@ public abstract class AbstractJaxRsApiTest {
Mockito.doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return invocation.getArgumentAt(4, ActionWithResult.class).run();
return invocation.getArgumentAt(4, Callable.class).call();
}
}).when(securityService).setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(Action.class));
@@ -90,14 +90,14 @@ public abstract class AbstractJaxRsApiTest {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
for (Object arg : invocation.getArguments()) {
if (arg instanceof ActionWithResult) {
return ((ActionWithResult) arg).run();
if (arg instanceof Callable) {
return ((Callable) arg).call();
}
}
return null;
}
}).when(securityService).setOwnershipCheckPermissionForObjectCreationAndRevertOnError(Mockito.any(),
Mockito.any(), Mockito.any(), Mockito.any(ActionWithResult.class));
Mockito.any(), Mockito.any(), Mockito.any(Callable.class));
Mockito.doReturn(true).when(securityService)
.hasCurrentUserReadPermission(Mockito.any(WithQualifiedObjectIdentifier.class));
@@ -15,6 +15,7 @@ import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Callable;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
@@ -47,7 +48,6 @@ import com.sap.sailing.domain.ranking.OneDesignRankingMetric;
import com.sap.sse.common.Color;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.security.ActionWithResult;
import com.sap.sse.security.SecurityService;
import com.sap.sse.security.interfaces.UserImpl;
import com.sap.sse.security.shared.Account;
@@ -86,9 +86,9 @@ public class RegattasResourceTest extends AbstractJaxRsApiTest {
series.add(testSeries);
final UUID closedRegattaUuid = UUID.randomUUID();
getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(SecuredDomainType.REGATTA,
Regatta.getTypeRelativeObjectIdentifier(closedRegattaName), closedRegattaName, new ActionWithResult<Regatta>() {
Regatta.getTypeRelativeObjectIdentifier(closedRegattaName), closedRegattaName, new Callable<Regatta>() {
@Override
public Regatta run() throws Exception {
public Regatta call() throws Exception {
return racingEventService.createRegatta(closedRegattaName, boatClassName,
/* canBoatsOfCompetitorsChangePerRace */ true, CompetitorRegistrationType.CLOSED,
/* registrationLinkSecret */ null, startDate, endDate, closedRegattaUuid, series,
@@ -99,9 +99,9 @@ public class RegattasResourceTest extends AbstractJaxRsApiTest {
}
});
getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(SecuredDomainType.REGATTA,
Regatta.getTypeRelativeObjectIdentifier(openRegattaName), openRegattaName, new ActionWithResult<Regatta>() {
Regatta.getTypeRelativeObjectIdentifier(openRegattaName), openRegattaName, new Callable<Regatta>() {
@Override
public Regatta run() throws Exception {
public Regatta call() throws Exception {
return racingEventService.createRegatta(openRegattaName, boatClassName,
/* canBoatsOfCompetitorsChangePerRace */ true,
CompetitorRegistrationType.OPEN_MODERATED, secret, startDate, endDate,
@@ -18,6 +18,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.Spliterator;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -32,6 +33,7 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@@ -94,7 +96,6 @@ import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.Util.Triple;
import com.sap.sse.common.impl.MillisecondsDurationImpl;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.security.ActionWithResult;
import com.sap.sse.security.shared.HasPermissions.DefaultActions;
import com.sap.sse.security.shared.RoleDefinition;
import com.sap.sse.security.shared.impl.User;
@@ -391,10 +392,10 @@ public class EventsResource extends AbstractSailingServerResource {
UUID regattaId = UUID.randomUUID();
Regatta regatta = getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
SecuredDomainType.REGATTA, Regatta.getTypeRelativeObjectIdentifier(regattaName),
regattaName, new ActionWithResult<Regatta>() {
regattaName, new Callable<Regatta>() {
@Override
public Regatta run() throws Exception {
public Regatta call() throws Exception {
return getService().apply(new AddSpecificRegatta(regattaName, boatClassName,
canBoatsOfCompetitorsChangePerRace, competitorRegistrationType, competitorRegistrationSecret, null, null, regattaId, regattaCreationParametersDTO,
/* isPersistent */ true, scoringScheme, courseAreaId, buoyZoneRadiusInHullLengths,
@@ -430,7 +431,25 @@ public class EventsResource extends AbstractSailingServerResource {
String eventName = eventNameParam == null ? getDefaultEventName() : eventNameParam;
String venueName = venueNameParam == null ? getDefaultVenueName(venueLat, venueLng) : venueNameParam;
if (createRegatta && boatClassName == null) {
throw new IllegalArgumentException(ExceptionManager.parameterRequiredMsg("boatClassName"));
throw new WebApplicationException(Response.status(Status.BAD_REQUEST)
.entity(ExceptionManager.parameterRequiredMsg("boatClassName")).type(MediaType.TEXT_PLAIN).build());
}
if (createLeaderboardGroup && getService().getLeaderboardGroupByName(createLeaderboardGroupParam) != null) {
throw new WebApplicationException(Response.status(Status.BAD_REQUEST)
.entity(ExceptionManager.objectAlreadyExists("leaderboard group", createLeaderboardGroupParam))
.type(MediaType.TEXT_PLAIN).build());
}
if (createRegatta) {
if (getService().getRegattaByName(createRegattaParam) != null) {
throw new WebApplicationException(Response.status(Status.BAD_REQUEST)
.entity(ExceptionManager.objectAlreadyExists("regatta", createRegattaParam))
.type(MediaType.TEXT_PLAIN).build());
}
if (getService().getLeaderboardByName(createRegattaParam) != null) {
throw new WebApplicationException(Response.status(Status.BAD_REQUEST)
.entity(ExceptionManager.objectAlreadyExists("leaderboard", createRegattaParam))
.type(MediaType.TEXT_PLAIN).build());
}
}
String eventDescription = eventDescriptionParam == null ? eventName : eventDescriptionParam;
final TimePoint startDate = parseTimePoint(startDateParam, startDateAsMillis, now());
@@ -452,9 +471,9 @@ public class EventsResource extends AbstractSailingServerResource {
StringUtils.join(CompetitorRegistrationType.values(), ", ")));
}
ActionWithResult<Util.Triple<Event, LeaderboardGroup, RegattaLeaderboard>> doCreationAction = new ActionWithResult<Util.Triple<Event, LeaderboardGroup, RegattaLeaderboard>>() {
Callable<Util.Triple<Event, LeaderboardGroup, RegattaLeaderboard>> doCreationAction = new Callable<Util.Triple<Event, LeaderboardGroup, RegattaLeaderboard>>() {
@Override
public Util.Triple<Event, LeaderboardGroup, RegattaLeaderboard> run() throws Exception {
public Util.Triple<Event, LeaderboardGroup, RegattaLeaderboard> call() throws Exception {
Event event = getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
SecuredDomainType.EVENT, EventBaseImpl.getTypeRelativeObjectIdentifier(eventId),
eventName, ()->getService().apply(new CreateEvent(eventName, eventDescription, startDate, endDate, venueName, isPublic, eventId,
@@ -513,7 +532,7 @@ public class EventsResource extends AbstractSailingServerResource {
getSecurityService().addUserToUserGroup(ownerGroup, getCurrentUser());
return getSecurityService().doWithTemporaryDefaultTenant(ownerGroup, doCreationAction);
} else {
return doCreationAction.run();
return doCreationAction.call();
}
} catch (Exception e) {
throw new RuntimeException(e);
@@ -529,10 +548,10 @@ public class EventsResource extends AbstractSailingServerResource {
LeaderboardGroup leaderboardGroup = getSecurityService()
.setOwnershipCheckPermissionForObjectCreationAndRevertOnError(SecuredDomainType.LEADERBOARD_GROUP,
LeaderboardGroupImpl.getTypeRelativeObjectIdentifier(leaderboardGroupId), leaderboardGroupName,
new ActionWithResult<LeaderboardGroup>() {
new Callable<LeaderboardGroup>() {
@Override
public LeaderboardGroup run() throws Exception {
public LeaderboardGroup call() throws Exception {
ScoringSchemeType overallLeaderboardScoringSchemeType = overallLeaderboardScoringSchemeTypeParam == null
? null : getScoringSchemeType(overallLeaderboardScoringSchemeTypeParam);
int[] overallLeaderboardDiscardThresholds = overallLeaderboardDiscardThresholdsParam == null ? new int[0] : overallLeaderboardDiscardThresholdsParam.stream().mapToInt(i -> i).toArray();
@@ -654,10 +673,10 @@ public class EventsResource extends AbstractSailingServerResource {
private RegattaLeaderboard createRegattaLeaderboard(String regattaName, int[] discardThresholds) {
return getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
SecuredDomainType.LEADERBOARD, Leaderboard.getTypeRelativeObjectIdentifier(regattaName), regattaName,
new ActionWithResult<RegattaLeaderboard>() {
new Callable<RegattaLeaderboard>() {
@Override
public RegattaLeaderboard run() throws Exception {
public RegattaLeaderboard call() throws Exception {
return getService()
.apply(new CreateRegattaLeaderboard(new RegattaName(regattaName), regattaName, discardThresholds));
}
@@ -13,6 +13,7 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -134,7 +135,6 @@ import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.impl.DegreeBearingImpl;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.security.ActionWithResult;
import com.sap.sse.security.shared.HasPermissions.DefaultActions;
import com.sap.sse.security.shared.OwnershipAnnotation;
import com.sap.sse.security.shared.WithQualifiedObjectIdentifier;
@@ -635,7 +635,7 @@ public class LeaderboardsResource extends AbstractLeaderboardsResource {
SecurityUtils.getSubject().checkPermission(SecuredDomainType.LEADERBOARD.getStringPermissionForObject(
DefaultActions.UPDATE, leaderboardAndRaceColumnAndFleetAndResponse.getLeaderboard()));
}
final ActionWithResult<Response> innerAction = () -> {
final Callable<Response> innerAction = () -> {
final Response result;
if (leaderboardAndRaceColumnAndFleetAndResponse.getFleet() != null) {
JSONObject jsonResult = new JSONObject();
@@ -670,7 +670,7 @@ public class LeaderboardsResource extends AbstractLeaderboardsResource {
final Response result;
if (groupOwner == null) {
result = innerAction.run();
result = innerAction.call();
} else {
result = getSecurityService().doWithTemporaryDefaultTenant(groupOwner, innerAction);
}
@@ -13,6 +13,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.function.Function;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -139,7 +140,6 @@ import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.common.impl.RGBColor;
import com.sap.sse.common.util.RoundingUtil;
import com.sap.sse.datamining.shared.impl.PredefinedQueryIdentifier;
import com.sap.sse.security.ActionWithResult;
import com.sap.sse.security.shared.HasPermissions.DefaultActions;
import com.sap.sse.security.shared.OwnershipAnnotation;
import com.sap.sse.security.shared.impl.User;
@@ -498,9 +498,9 @@ public class RegattasResource extends AbstractSailingServerResource {
if (subject.isAuthenticated()) {
competitor = getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
SecuredDomainType.COMPETITOR, CompetitorImpl.getTypeRelativeObjectIdentifier(competitorUuid), name,
new ActionWithResult<CompetitorWithBoat>() {
new Callable<CompetitorWithBoat>() {
@Override
public CompetitorWithBoat run() throws Exception {
public CompetitorWithBoat call() throws Exception {
return getService().getCompetitorAndBoatStore().getOrCreateCompetitorWithBoat(
competitorUuid, name, shortName, color, email, flagImageURI, team,
timeOnTimeFactor,
@@ -575,10 +575,10 @@ public class RegattasResource extends AbstractSailingServerResource {
if (SecurityUtils.getSubject().isAuthenticated()) {
boat = getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
SecuredDomainType.BOAT, BoatImpl.getTypeRelativeObjectIdentifier(boatUUID), name,
new ActionWithResult<DynamicBoat>() {
new Callable<DynamicBoat>() {
@Override
public DynamicBoat run() throws Exception {
public DynamicBoat call() throws Exception {
return new BoatImpl(boatUUID, name, getService().getBaseDomainFactory()
.getOrCreateBoatClass(boatClassName, /* typicallyStartsUpwind */ true), sailId);
}
@@ -44,4 +44,9 @@ public class ExceptionManager implements ExceptionMapper<Exception> {
return "The value \"" + StringEscapeUtils.escapeHtml(value) + "\" is not recognized. Correct values are: "
+ correctValues;
}
public static String objectAlreadyExists(String objectTypeName, String objectName) {
return "The \"" + StringEscapeUtils.escapeHtml(objectTypeName) + "\" with name \""
+ StringEscapeUtils.escapeHtml(objectName) + "\" already exists.";
}
}
@@ -16,6 +16,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -105,7 +106,6 @@ import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.Util.Triple;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.i18n.ResourceBundleStringMessages;
import com.sap.sse.security.ActionWithResult;
import com.sap.sse.security.SecurityService;
import com.sap.sse.security.shared.HasPermissions.DefaultActions;
import com.sap.sse.security.shared.TypeRelativeObjectIdentifier;
@@ -464,7 +464,7 @@ public class ExpeditionAllInOneImporter {
* persist and the result of the action is returned.
*/
private <T> T checkTrackedRacesCreationPermission(final String regattaName, final String trackedRaceName,
final Iterable<String> additionalTrackedRaceNames, final ActionWithResult<T> action) {
final Iterable<String> additionalTrackedRaceNames, final Callable<T> action) {
Iterator<String> additionalTrackedRaceNamesIterator = additionalTrackedRaceNames.iterator();
return checkTrackedRaceCreationPermission(regattaName, trackedRaceName, ()->{
return checkTrackedRaceCreationPermissionRecursively(regattaName, additionalTrackedRaceNamesIterator, action);
@@ -472,16 +472,16 @@ public class ExpeditionAllInOneImporter {
}
private <T> T checkTrackedRaceCreationPermissionRecursively(final String regattaName, final Iterator<String> additionalTrackedRaceNamesIterator,
final ActionWithResult<T> terminalAction) throws Exception {
final Callable<T> terminalAction) throws Exception {
if (additionalTrackedRaceNamesIterator.hasNext()) {
return checkTrackedRaceCreationPermission(regattaName, additionalTrackedRaceNamesIterator.next(),
()->checkTrackedRaceCreationPermissionRecursively(regattaName, additionalTrackedRaceNamesIterator, terminalAction));
} else {
return terminalAction.run();
return terminalAction.call();
}
}
private <T> T checkTrackedRaceCreationPermission(String regattaName, String trackedRaceName, ActionWithResult<T> action) {
private <T> T checkTrackedRaceCreationPermission(String regattaName, String trackedRaceName, Callable<T> action) {
return securityService.setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
TrackedRace.getSecuredDomainType(),
TrackedRace.getIdentifier(new RegattaNameAndRaceName(regattaName, trackedRaceName)).getTypeRelativeObjectIdentifier(),
@@ -159,6 +159,9 @@ public abstract class AbstractWindImporter {
public void importWindToWindSourceAndTrackedRaces(RacingEventService service, WindImportResult windImportResult, WindSource windSource,
List<DynamicTrackedRace> trackedRaces, final Map<InputStream, String> streamsWithFilenames)
throws IOException, InterruptedException, FormatNotSupportedException {
for (DynamicTrackedRace trackedRace : trackedRaces) {
service.getSecurityService().checkCurrentUserUpdatePermission(trackedRace);
}
Iterable<Wind> windFixes = importWind(streamsWithFilenames);
if (!Util.isEmpty(windFixes)) {
for (DynamicTrackedRace trackedRace : trackedRaces) {
@@ -29,7 +29,8 @@
</tr>
<tr>
<td>Optional parameters:</td>
<td>None</td>
<td>leaderboardname: the leaderboardName, required for evaluation of the secret <br>
secret: in case the given secret is equal to the one stored in a regatta with the same name as the leaderboardName, further security checks will be skipped</td>
</tr>
<tr>
<td>Request method:</td>
@@ -29,7 +29,8 @@
</tr>
<tr>
<td>Optional parameters:</td>
<td>None</td>
<td>leaderboardname: the leaderboardName, required for evaluation of the secret <br>
secret: in case the given secret is equal to the one stored in a regatta with the same name as the leaderboardName, further security checks will be skipped</td>
</tr>
<tr>
<td>Request method:</td>
@@ -29,7 +29,7 @@
</tr>
<tr>
<td>Optional parameters:</td>
<td>resultState [Live = Default, Final] </td>
<td>resultState [Live = Default, Final], secret: in case the given secret is equal to the one stored in a regatta with the same name as the {name}, further security checks will be skipped</td>
</tr>
<tr>
<td>&nbsp;</td>
@@ -30,7 +30,7 @@ All slashes contained within the {regattaname} parameter must be replaced by "__
</tr>
<tr>
<td>Optional parameters:</td>
<td>None</td>
<td>secret: in case the given secret is equal to the one stored in the regatta with the given name, further security checks will be skipped</td>
</tr>
<tr>
<td>Request method:</td>
@@ -38,7 +38,7 @@ There is also the 'ALL' shortcut constant which can be used to get all available
</tr>
<tr>
<td>Mandatory parameters:</td>
<td>None</td>
<td>secret: in case the given secret is equal to the one stored in a regatta with the same name as the {name}, further security checks will be skipped</td>
</tr>
<tr>
<td>Optional parameters:</td>
@@ -63,7 +63,14 @@ import com.sap.sse.security.SecurityInitializationCustomizer;
import com.sap.sse.security.SecurityService;
import com.sap.sse.security.interfaces.PreferenceConverter;
import com.sap.sse.security.shared.HasPermissionsProvider;
import com.sap.sse.security.shared.QualifiedObjectIdentifier;
import com.sap.sse.security.shared.RoleDefinition;
import com.sap.sse.security.shared.TypeRelativeObjectIdentifier;
import com.sap.sse.security.shared.WildcardPermission;
import com.sap.sse.security.shared.HasPermissions.DefaultActions;
import com.sap.sse.security.shared.impl.PermissionAndRoleAssociation;
import com.sap.sse.security.shared.impl.SecuredSecurityTypes;
import com.sap.sse.security.shared.impl.User;
import com.sap.sse.util.ClearStateTestSupport;
import com.sap.sse.util.ServiceTrackerFactory;
@@ -213,6 +220,16 @@ public class Activator implements BundleActivator {
if (securityService.isInitialOrMigration()) {
securityService.putRoleDefinitionToUserGroup(securityService.getDefaultTenant(),
sailingViewerRoleDefinition, true);
WildcardPermission permission = sailingViewerRoleDefinition.getIdentifier()
.getPermission(DefaultActions.READ);
final User allUser = securityService.getAllUser();
securityService.addPermissionForUser(allUser.getName(), permission);
TypeRelativeObjectIdentifier associationTypeIdentifier = PermissionAndRoleAssociation
.get(permission, allUser);
QualifiedObjectIdentifier qualifiedTypeIdentifier = SecuredSecurityTypes.PERMISSION_ASSOCIATION
.getQualifiedObjectIdentifier(associationTypeIdentifier);
securityService.setOwnership(qualifiedTypeIdentifier, allUser, null);
}
}, null));
@@ -33,7 +33,6 @@ import com.sap.sse.common.Util.Triple;
import com.sap.sse.common.mail.MailException;
import com.sap.sse.gwt.client.ServerInfoDTO;
import com.sap.sse.security.Action;
import com.sap.sse.security.ActionWithResult;
import com.sap.sse.security.SecurityService;
import com.sap.sse.security.interfaces.Credential;
import com.sap.sse.security.shared.AccessControlListAnnotation;
@@ -124,10 +123,10 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U
public RoleDefinitionDTO createRoleDefinition(String roleDefinitionIdAsString, String name) {
RoleDefinition role = getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
SecuredSecurityTypes.ROLE_DEFINITION, new TypeRelativeObjectIdentifier(roleDefinitionIdAsString), name,
new ActionWithResult<RoleDefinition>() {
new Callable<RoleDefinition>() {
@Override
public RoleDefinition run() throws Exception {
public RoleDefinition call() throws Exception {
return getSecurityService().createRoleDefinition(UUID.fromString(roleDefinitionIdAsString),
name);
}
@@ -490,9 +489,9 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U
throws UserManagementException, MailException, UnauthorizedException {
User user = getSecurityService().checkPermissionForObjectCreationAndRevertOnErrorForUserCreation(username,
new ActionWithResult<User>() {
new Callable<User>() {
@Override
public User run() throws Exception {
public User call() throws Exception {
try {
User newUser = getSecurityService().createSimpleUser(username, email, password, fullName,
company,
@@ -908,10 +907,10 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U
final QualifiedObjectIdentifier qualifiedTypeIdentifier = SecuredSecurityTypes.ROLE_ASSOCIATION
.getQualifiedObjectIdentifier(associationTypeIdentifier);
getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(qualifiedTypeIdentifier,
new ActionWithResult<Void>() {
new Callable<Void>() {
@Override
public Void run() throws Exception {
public Void call() throws Exception {
getSecurityService().removeRoleFromUser(user, role);
logger.info(message);
return null;
@@ -1051,9 +1050,9 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U
.getQualifiedObjectIdentifier(associationTypeIdentifier);
getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(qualifiedTypeIdentifier,
new ActionWithResult<Void>() {
new Callable<Void>() {
@Override
public Void run() throws Exception {
public Void call() throws Exception {
getSecurityService().removePermissionFromUser(username, permission);
logger.info(message);
return null;
@@ -1,6 +0,0 @@
package com.sap.sse.security;
@FunctionalInterface
public interface ActionWithResult<T> {
T run() throws Exception;
}
@@ -5,6 +5,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -354,7 +355,7 @@ public interface SecurityService extends ReplicableWithObjectInputStream<Replica
<T> T setOwnershipCheckPermissionForObjectCreationAndRevertOnError(HasPermissions type,
TypeRelativeObjectIdentifier typeRelativeObjectIdentifier,
String securityDisplayName, ActionWithResult<T> createActionReturningCreatedObject);
String securityDisplayName, Callable<T> createActionReturningCreatedObject);
void setOwnershipCheckPermissionForObjectCreationAndRevertOnError(HasPermissions type,
TypeRelativeObjectIdentifier typeRelativeObjectIdentifier, String securityDisplayName, Action actionToCreateObject);
@@ -365,7 +366,7 @@ public interface SecurityService extends ReplicableWithObjectInputStream<Replica
Action actionToDeleteObject);
<T> T checkPermissionAndDeleteOwnershipForObjectRemoval(WithQualifiedObjectIdentifier object,
ActionWithResult<T> actionToDeleteObject);
Callable<T> actionToDeleteObject);
void deleteAllDataForRemovedObject(QualifiedObjectIdentifier identifier);
@@ -516,16 +517,16 @@ public interface SecurityService extends ReplicableWithObjectInputStream<Replica
void copyUsersAndRoleAssociations(UserGroup source, UserGroup destination, RoleCopyListener callback);
User checkPermissionForObjectCreationAndRevertOnErrorForUserCreation(String username,
ActionWithResult<User> createActionReturningCreatedObject);
Callable<User> createActionReturningCreatedObject);
/**
* Do only use this, if it is not possible to get the actual instance of the object to delete using the
* WithQualifiedObjectIdentifier variant
*/
<T> T checkPermissionAndDeleteOwnershipForObjectRemoval(QualifiedObjectIdentifier identifier,
ActionWithResult<T> actionToDeleteObject);
Callable<T> actionToDeleteObject);
<T> T doWithTemporaryDefaultTenant(UserGroup tenant, ActionWithResult<T> action);
<T> T doWithTemporaryDefaultTenant(UserGroup tenant, Callable<T> action);
/**
* Before using a SecuritySystem, it is necessary to initialize the service, to ensure roles and acls are correctly
@@ -20,6 +20,7 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentSkipListSet;
@@ -85,7 +86,6 @@ import com.sap.sse.replication.OperationsToMasterSendingQueue;
import com.sap.sse.replication.ReplicationMasterDescriptor;
import com.sap.sse.replication.ReplicationService;
import com.sap.sse.security.Action;
import com.sap.sse.security.ActionWithResult;
import com.sap.sse.security.BearerAuthenticationToken;
import com.sap.sse.security.ClientUtils;
import com.sap.sse.security.GithubApi;
@@ -111,6 +111,7 @@ import com.sap.sse.security.shared.HasPermissions.DefaultActions;
import com.sap.sse.security.shared.HasPermissionsProvider;
import com.sap.sse.security.shared.OwnershipAnnotation;
import com.sap.sse.security.shared.PermissionChecker;
import com.sap.sse.security.shared.PredefinedRoles;
import com.sap.sse.security.shared.QualifiedObjectIdentifier;
import com.sap.sse.security.shared.RoleDefinition;
import com.sap.sse.security.shared.RolePrototype;
@@ -325,6 +326,15 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
// Permission association is owned by the server tenant.
// This typically ensures that the server admin is able to remove the association.
setOwnership(qualifiedTypeIdentifierForPermission, null, getDefaultTenant());
// All users may read the initial set of RoleDefinition to be able to assign those roles to other users
for (UUID predefinedRoleId : getPredefinedRoleIds()) {
final RoleDefinition predefinedRole = getRoleDefinition(predefinedRoleId);
if (predefinedRole != null) {
addPermissionForUserAndSetUserAsOwner(allUser,
predefinedRole.getIdentifier().getPermission(DefaultActions.READ));
}
}
}
} catch (UserManagementException | MailException | UserGroupManagementException e) {
logger.log(Level.SEVERE,
@@ -332,6 +342,16 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
}
}
private Iterable<UUID> getPredefinedRoleIds() {
final Set<UUID> predefinedRoleIds = new HashSet<>();
predefinedRoleIds.add(AdminRole.getInstance().getId());
predefinedRoleIds.add(UserRole.getInstance().getId());
for (final PredefinedRoles otherPredefinedRole : PredefinedRoles.values()) {
predefinedRoleIds.add(otherPredefinedRole.getId());
}
return predefinedRoleIds;
}
private void initEmptyAccessControlStore() {
}
@@ -1079,6 +1099,14 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
.getQualifiedObjectIdentifier(associationTypeIdentifier);
setOwnership(qualifiedTypeIdentifier, user, null);
}
public void addPermissionForUserAndSetUserAsOwner(User user, WildcardPermission permission) {
addPermissionForUser(user.getName(), permission);
TypeRelativeObjectIdentifier associationTypeIdentifier = PermissionAndRoleAssociation.get(permission, user);
QualifiedObjectIdentifier qualifiedTypeIdentifier = SecuredSecurityTypes.PERMISSION_ASSOCIATION
.getQualifiedObjectIdentifier(associationTypeIdentifier);
setOwnership(qualifiedTypeIdentifier, user, null);
}
@Override
public void addRoleForUser(User user, Role role) {
@@ -1614,7 +1642,7 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
@Override
public <T> T setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
HasPermissions type, TypeRelativeObjectIdentifier typeIdentifier, String securityDisplayName,
ActionWithResult<T> actionWithResult) {
Callable<T> actionWithResult) {
QualifiedObjectIdentifier identifier = type.getQualifiedObjectIdentifier(typeIdentifier);
T result = null;
boolean didSetOwnership = false;
@@ -1631,7 +1659,7 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
ServerActions.CREATE_OBJECT, new TypeRelativeObjectIdentifier(ServerInfo.getName())));
SecurityUtils.getSubject()
.checkPermission(identifier.getStringPermission(DefaultActions.CREATE));
result = actionWithResult.run();
result = actionWithResult.call();
} catch (AuthorizationException e) {
if (didSetOwnership) {
deleteOwnership(identifier);
@@ -1675,13 +1703,13 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
*/
@Override
public User checkPermissionForObjectCreationAndRevertOnErrorForUserCreation(String username,
ActionWithResult<User> createActionReturningCreatedObject) {
Callable<User> createActionReturningCreatedObject) {
QualifiedObjectIdentifier identifier = SecuredSecurityTypes.USER
.getQualifiedObjectIdentifier(UserImpl.getTypeRelativeObjectIdentifier(username));
User result = null;
try {
SecurityUtils.getSubject().checkPermission(identifier.getStringPermission(DefaultActions.CREATE));
result = createActionReturningCreatedObject.run();
result = createActionReturningCreatedObject.call();
} catch (AuthorizationException e) {
throw e;
} catch (Exception e) {
@@ -1701,17 +1729,17 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
@Override
public <T> T checkPermissionAndDeleteOwnershipForObjectRemoval(WithQualifiedObjectIdentifier object,
ActionWithResult<T> actionToDeleteObject) {
Callable<T> actionToDeleteObject) {
QualifiedObjectIdentifier identifier = object.getIdentifier();
return checkPermissionAndDeleteOwnershipForObjectRemoval(identifier, actionToDeleteObject);
}
@Override
public <T> T checkPermissionAndDeleteOwnershipForObjectRemoval(QualifiedObjectIdentifier identifier,
ActionWithResult<T> actionToDeleteObject) {
Callable<T> actionToDeleteObject) {
try {
SecurityUtils.getSubject().checkPermission(identifier.getStringPermission(DefaultActions.DELETE));
final T result = actionToDeleteObject.run();
final T result = actionToDeleteObject.call();
deleteAllDataForRemovedObject(identifier);
return result;
} catch (Exception e) {
@@ -2219,11 +2247,11 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
}
@Override
public <T> T doWithTemporaryDefaultTenant(UserGroup tenant, ActionWithResult<T> action) {
public <T> T doWithTemporaryDefaultTenant(UserGroup tenant, Callable<T> action) {
final UserGroup previousValue = temporaryDefaultTenant.get();
temporaryDefaultTenant.set(tenant);
try {
return action.run();
return action.call();
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
@@ -1,6 +1,7 @@
package com.sap.sse.security.jaxrs.api;
import java.util.Locale;
import java.util.concurrent.Callable;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
@@ -23,7 +24,6 @@ import org.json.simple.JSONObject;
import com.sap.sse.common.Util;
import com.sap.sse.common.mail.MailException;
import com.sap.sse.security.ActionWithResult;
import com.sap.sse.security.jaxrs.AbstractSecurityResource;
import com.sap.sse.security.shared.UserManagementException;
import com.sap.sse.security.shared.impl.User;
@@ -115,10 +115,10 @@ public class SecurityResource extends AbstractSecurityResource {
try {
User user = getService().checkPermissionForObjectCreationAndRevertOnErrorForUserCreation(username,
new ActionWithResult<User>() {
new Callable<User>() {
@Override
public User run() throws Exception {
public User call() throws Exception {
final String validationBaseURL = getEmailValidationBaseURL(uriInfo);
User newUser = getService().createSimpleUser(username, email, password, fullName, company,
Locale.ENGLISH, validationBaseURL, getService().getDefaultTenantForCurrentUser());