Merge branch 'permission-vertical' into bug4813

Conflicts:
	java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java
	java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/EventsResource.java
This commit is contained in:
Thomas Wiese committed 2018-12-12 17:41:03 +01:00
commit 320ac4a597
12 files changed
+203 -96

No files matched your search

@@ -242,19 +242,22 @@ public class AdminConsoleEntryPoint extends AbstractSailingEntryPoint
this, this, getStringMessages());
tractracEventManagementPanel.ensureDebugId("TracTracEventManagement");
panel.addToTabPanel(connectorsTabPanel, new DefaultRefreshableAdminConsolePanel<TracTracEventManagementPanel>(tractracEventManagementPanel),
getStringMessages().tracTracEvents()); // no permissions required; we show those TracTrac connector stuff the user may read
getStringMessages().tracTracEvents(),
SecuredDomainType.TRACTRAC_ACCOUNT.getPermission(DefaultActions.values()));
regattasDisplayers.add(tractracEventManagementPanel);
SwissTimingReplayConnectorPanel swissTimingReplayConnectorPanel = new SwissTimingReplayConnectorPanel(
getSailingService(), this, this, getStringMessages());
panel.addToTabPanel(connectorsTabPanel, new DefaultRefreshableAdminConsolePanel<SwissTimingReplayConnectorPanel>(swissTimingReplayConnectorPanel),
getStringMessages().swissTimingArchiveConnector()); // no permissions required; we show those SwissTiming connector stuff the user may read
getStringMessages().swissTimingArchiveConnector(),
SecuredDomainType.SWISS_TIMING_ARCHIVE_ACCOUNT.getPermission(DefaultActions.values()));
regattasDisplayers.add(swissTimingReplayConnectorPanel);
SwissTimingEventManagementPanel swisstimingEventManagementPanel = new SwissTimingEventManagementPanel(
getSailingService(), this, this, getStringMessages());
panel.addToTabPanel(connectorsTabPanel, new DefaultRefreshableAdminConsolePanel<SwissTimingEventManagementPanel>(swisstimingEventManagementPanel),
getStringMessages().swissTimingEvents()); // no permissions required; we show those SwissTiming connector stuff the user may read
getStringMessages().swissTimingEvents(),
SecuredDomainType.SWISS_TIMING_ACCOUNT.getPermission(DefaultActions.values()));
regattasDisplayers.add(swisstimingEventManagementPanel);
final SmartphoneTrackingEventManagementPanel raceLogTrackingEventManagementPanel = new SmartphoneTrackingEventManagementPanel(
@@ -272,8 +275,8 @@ public class AdminConsoleEntryPoint extends AbstractSailingEntryPoint
IgtimiAccountsPanel igtimiAccountsPanel = new IgtimiAccountsPanel(getSailingService(), this, getStringMessages());
igtimiAccountsPanel.ensureDebugId("IgtimiAccounts");
panel.addToTabPanel(connectorsTabPanel, new DefaultRefreshableAdminConsolePanel<IgtimiAccountsPanel>(igtimiAccountsPanel),
getStringMessages().igtimiAccounts()); // Igtimi accounts are displayed based on permissions
getStringMessages().igtimiAccounts(),
SecuredDomainType.IGTIMI_ACCOUNT.getPermission(DefaultActions.values()));
ExpeditionDeviceConfigurationsPanel expeditionDeviceConfigurationsPanel = new ExpeditionDeviceConfigurationsPanel(getSailingService(), this, getStringMessages());
expeditionDeviceConfigurationsPanel.ensureDebugId("ExpeditionDeviceConfigurations");
panel.addToTabPanel(connectorsTabPanel, new DefaultRefreshableAdminConsolePanel<ExpeditionDeviceConfigurationsPanel>(expeditionDeviceConfigurationsPanel) {
@@ -281,12 +284,13 @@ public class AdminConsoleEntryPoint extends AbstractSailingEntryPoint
public void refreshAfterBecomingVisible() {
expeditionDeviceConfigurationsPanel.refresh();
}
}, getStringMessages().expeditionDeviceConfigurations()); // Expedition device configurations are displayed based on individual user permissions
}, getStringMessages().expeditionDeviceConfigurations(),
SecuredDomainType.EXPEDITION_DEVICE_CONFIGURATION.getPermission(DefaultActions.values()));
ResultImportUrlsManagementPanel resultImportUrlsManagementPanel = new ResultImportUrlsManagementPanel(getSailingService(), this, getStringMessages());
panel.addToTabPanel(connectorsTabPanel, new DefaultRefreshableAdminConsolePanel<ResultImportUrlsManagementPanel>(resultImportUrlsManagementPanel),
getStringMessages().resultImportUrls()); // result import URLs have ownerships and are displayed as the user can see / update / delete them
getStringMessages().resultImportUrls(),
SecuredDomainType.RESULT_IMPORT_URL.getPermission(DefaultActions.values()));
StructureImportManagementPanel structureImportUrlsManagementPanel = new StructureImportManagementPanel(
getSailingService(), getUserService(), this, getStringMessages(), this, eventManagementPanel);
panel.addToTabPanel(connectorsTabPanel, new DefaultRefreshableAdminConsolePanel<StructureImportManagementPanel>(structureImportUrlsManagementPanel),
@@ -315,7 +319,7 @@ public class AdminConsoleEntryPoint extends AbstractSailingEntryPoint
panel.addToTabPanel(advancedTabPanel, new DefaultRefreshableAdminConsolePanel<RemoteServerInstancesManagementPanel>(remoteServerInstancesManagementPanel),
getStringMessages().remoteServerInstances(),
SecuredSecurityTypes.SERVER.getPermissionForObject(
SecuredSecurityTypes.ServerActions.CONFIGURE_LOCAL_SERVER, serverInfo.getServerName()));
SecuredSecurityTypes.ServerActions.CONFIGURE_REMOTE_INSTANCES, serverInfo.getServerName()));
LocalServerManagementPanel localServerInstancesManagementPanel = new LocalServerManagementPanel(getSailingService(), this, getStringMessages());
panel.addToTabPanel(advancedTabPanel, new DefaultRefreshableAdminConsolePanel<LocalServerManagementPanel>(localServerInstancesManagementPanel),
@@ -4636,45 +4636,34 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
public void removeRegatta(RegattaIdentifier regattaIdentifier) {
Regatta regatta = getService().getRegatta(regattaIdentifier);
if (regatta != null) {
getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(regatta, new Action() {
@Override
public void run() throws Exception {
// if there were any tracked races, free all ownerships
for (RaceDefinition race : regatta.getAllRaces()) {
String typeRelativeObjectIdentifier = WildcardPermissionEncoder.encode(regatta.getName(),
race.getName());
QualifiedObjectIdentifier identifier = SecuredDomainType.TRACKED_RACE
.getQualifiedObjectIdentifier(typeRelativeObjectIdentifier);
getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(identifier,
new ActionWithResult<Void>() {
@Override
public Void run() throws Exception {
RegattaNameAndRaceName raceIdentifier = new RegattaNameAndRaceName(
regatta.getName(), race.getName());
ArrayList<RegattaAndRaceIdentifier> trackedRace = new ArrayList<>();
trackedRace.add(raceIdentifier);
removeAndUntrackRaces(trackedRace);
return null;
}
});
// remove all leaderboards using the proper call that will clean and remove the owner as well
Set<RegattaLeaderboard> leaderboardsToRemove = new HashSet<>();
for (Leaderboard leaderboard : getService().getLeaderboards().values()) {
if (leaderboard instanceof RegattaLeaderboard) {
RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboard;
if (regattaLeaderboard.getRegatta() == regatta) {
leaderboardsToRemove.add(regattaLeaderboard);
}
}
}
for (RegattaLeaderboard regattaLeaderboardToRemove : leaderboardsToRemove) {
removeLeaderboard(regattaLeaderboardToRemove.getName());
}
Set<QualifiedObjectIdentifier> objectsThatWillBeImplicitlyCleanedByRemoveRegatta = new HashSet<>();
objectsThatWillBeImplicitlyCleanedByRemoveRegatta.add(regatta.getIdentifier());
for (RaceDefinition race : regatta.getAllRaces()) {
String typeRelativeObjectIdentifier = WildcardPermissionEncoder.encode(regatta.getName(),
race.getName());
QualifiedObjectIdentifier identifier = SecuredDomainType.TRACKED_RACE
.getQualifiedObjectIdentifier(typeRelativeObjectIdentifier);
objectsThatWillBeImplicitlyCleanedByRemoveRegatta.add(identifier);
}
for (Leaderboard leaderboard : getService().getLeaderboards().values()) {
if (leaderboard instanceof RegattaLeaderboard) {
RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboard;
if (regattaLeaderboard.getRegatta() == regatta) {
objectsThatWillBeImplicitlyCleanedByRemoveRegatta.add(regattaLeaderboard.getIdentifier());
}
getService().apply(new RemoveRegatta(regattaIdentifier));
}
});
}
// check if we can delete everything RemoveRegatta will remove
for (QualifiedObjectIdentifier toRemovePermissionObjects : objectsThatWillBeImplicitlyCleanedByRemoveRegatta) {
getSecurityService().checkCurrentUserDeletePermission(toRemovePermissionObjects);
}
// we have all permissions, execute
getService().apply(new RemoveRegatta(regattaIdentifier));
// cleanup the Ownership and ACLs
for (QualifiedObjectIdentifier toRemovePermissionObjects : objectsThatWillBeImplicitlyCleanedByRemoveRegatta) {
getSecurityService().deleteOwnership(toRemovePermissionObjects);
}
}
}
@@ -0,0 +1,22 @@
package com.sap.sailing.server.gateway.deserialization.impl;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import com.sap.sailing.domain.common.Position;
import com.sap.sailing.domain.common.impl.DegreePosition;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
import com.sap.sailing.server.gateway.serialization.impl.MongoDbFriendlyPositionJsonSerializer;
public class MongoDbFriendlyPositionJsonDeserializer implements JsonDeserializer<Position> {
@Override
public Position deserialize(JSONObject object) throws JsonDeserializationException {
JSONArray coordinatesJson = (JSONArray) object.get(MongoDbFriendlyPositionJsonSerializer.FIELD_COORDINATES);
Number longitudeDeg = (Number) coordinatesJson.get(0);
Number latitudeDeg = (Number) coordinatesJson.get(1);
return new DegreePosition(latitudeDeg.doubleValue(), longitudeDeg.doubleValue());
}
}
@@ -0,0 +1,26 @@
package com.sap.sailing.server.gateway.serialization.impl;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import com.sap.sailing.domain.common.Position;
import com.sap.sailing.server.gateway.serialization.JsonSerializer;
public class MongoDbFriendlyPositionJsonSerializer implements JsonSerializer<Position> {
public static final String FIELD_TYPE = "type";
public static final String FIELD_TYPE_VALUE = "Point";
public static final String FIELD_COORDINATES = "coordinates";
@Override
public JSONObject serialize(Position position) {
JSONObject result = new JSONObject();
JSONArray coordinates = new JSONArray();
coordinates.add(position.getLngDeg());
coordinates.add(position.getLatDeg());
result.put(FIELD_TYPE, FIELD_TYPE_VALUE);
result.put(FIELD_COORDINATES, coordinates);
return result;
}
}
@@ -31,7 +31,7 @@ public class RaceWindJsonSerializer extends AbstractTrackedRaceDataJsonSerialize
public static final String SAMPLING_RATE = "samplingRate";
public static final String FIXES = "fixes";
private final PositionJsonSerializer positionSerializer = new PositionJsonSerializer();
private final MongoDbFriendlyPositionJsonSerializer positionSerializer = new MongoDbFriendlyPositionJsonSerializer();
private final WindJsonSerializer windSerializer = new WindJsonSerializer(positionSerializer);
@Override
@@ -85,7 +85,8 @@ public class RaceWindJsonSerializer extends AbstractTrackedRaceDataJsonSerialize
windSourceJson.put(FIRST_POSITION, positionSerializer.serialize(firstWindSourcePosition));
windSourceJson.put(START_TIME_POINT, firstWindSourceTimePoint.asMillis());
windSourceJson.put(END_TIME_POINT, lastWindSourceTimePoint.asMillis());
double samplingRate = duration.asSeconds() > 0 ? windFixesJson.size() / duration.asSeconds() : 0;
double samplingRate = duration.asSeconds() > 0 ? windFixesJson.size() / duration.asSeconds()
: 0;
windSourceJson.put(SAMPLING_RATE, samplingRate);
windSourceJson.put(FIXES, windFixesJson);
windSourcesJson.add(windSourceJson);
@@ -55,8 +55,8 @@ authc.successUrl = /api/restsecurity/hello
# authentication with POST parameters "username" and "password".
bearerToken = com.sap.sailing.server.security.BearerTokenOrBasicOrFormAuthenticationFilterSAPSailing
# The same as bearerToken, but with additional fallback to anonymous authentification.
# In this case sufficent permission checks have to be done on the application side.
# The same as bearerToken, but with additional fallback to anonymous authentication.
# In this case sufficient permission checks have to be done on the application side.
bearerTokenOrAnonymous = com.sap.sailing.server.security.BearerTokenOrBasicOrFormOrAnonymousAuthenticationFilterSAPSailing
# Specifying filter chains for URL patterns
@@ -93,6 +93,7 @@ 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.impl.User;
import com.sap.sse.security.shared.impl.UserGroup;
import com.sap.sse.shared.media.ImageDescriptor;
import com.sap.sse.shared.media.VideoDescriptor;
@@ -417,27 +418,7 @@ public class EventsResource extends AbstractSailingServerResource {
Map<Locale, URL> sailorsInfoWebsiteURLs = new HashMap<Locale,URL>();
Iterable<ImageDescriptor> images = Collections.<ImageDescriptor> emptyList();
Iterable<VideoDescriptor> videos = Collections.<VideoDescriptor> emptyList();
Event event = getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
SecuredDomainType.EVENT, eventId,
eventName, new ActionWithResult<Event>() {
@Override
public Event run() throws Exception {
return getService()
.apply(new CreateEvent(eventName, eventDescription, startDate, endDate, venueName, isPublic, eventId,
officialWebsiteURL, baseURL, sailorsInfoWebsiteURLs, images, videos, leaderboardGroupIds));
}
});
CourseArea courseArea = addCourseArea(event, "Default");
final LeaderboardGroup leaderboardGroup;
if (createLeaderboardGroup) {
leaderboardGroup = validateAndAddLeaderboardGroup(event.getId(), event.getName(), event.getDescription(), /* leaderboardGroupDisplayNameParam */ null,
/* displayGroupsInReverseOrderParam */ false, /* leaderboardNamesParam */ null,
/* overallLeaderboardDiscardThresholdsParam */ null, /* overallLeaderboardScoringSchemeTypeParam */ null);
} else {
leaderboardGroup = null;
}
final CompetitorRegistrationType competitorRegistrationType;
try {
competitorRegistrationType = CompetitorRegistrationType.valueOfOrDefault(competitorRegistrationTypeString, /* failForUnknown */ true);
@@ -445,27 +426,68 @@ public class EventsResource extends AbstractSailingServerResource {
throw new IllegalArgumentException(ExceptionManager.incorrectParameterValue(competitorRegistrationTypeString,
StringUtils.join(CompetitorRegistrationType.values(), ", ")));
}
final RegattaLeaderboard leaderboard;
if (createRegatta) {
leaderboard = validateAndCreateRegatta(event.getName(), boatClassName,
/* scoringSchemeParam */ null, courseArea.getId(), /* buoyZoneRadiusInHullLengthsParam */ null,
/* useStartTimeInterferenceParam */ null, /* controlTrackingFromStartAndFinishTimesParam */ null,
/* rankingMetricParam */ null, /* leaderboardDiscardThresholdsParam */ null,
numberOfRacesParam, canBoatsOfCompetitorsChangePerRace, competitorRegistrationType, competitorRegistrationSecret);
if (leaderboardGroup != null) {
getService().apply(new UpdateLeaderboardGroup(leaderboardGroup.getName(), leaderboardGroup.getName(),
leaderboardGroup.getDescription(), leaderboardGroup.getDisplayName(),
Collections.singletonList(leaderboard.getName()),
leaderboardGroup.getOverallLeaderboard() == null ? null
: ((ThresholdBasedResultDiscardingRule) leaderboardGroup.getOverallLeaderboard()
.getResultDiscardingRule()).getDiscardIndexResultsStartingWithHowManyRaces(),
leaderboardGroup.getOverallLeaderboard() == null ? null
: leaderboardGroup.getOverallLeaderboard().getScoringScheme().getType()));
ActionWithResult<Util.Triple<Event, LeaderboardGroup, RegattaLeaderboard>> doCreationAction = new ActionWithResult<Util.Triple<Event, LeaderboardGroup, RegattaLeaderboard>>() {
@Override
public Util.Triple<Event, LeaderboardGroup, RegattaLeaderboard> run() throws Exception {
Event event = getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
SecuredDomainType.EVENT, eventId,
eventName, new ActionWithResult<Event>() {
@Override
public Event run() throws Exception {
return getService()
.apply(new CreateEvent(eventName, eventDescription, startDate, endDate, venueName, isPublic, eventId,
officialWebsiteURL, baseURL, sailorsInfoWebsiteURLs, images, videos, leaderboardGroupIds));
}
});
CourseArea courseArea = addCourseArea(event.getId(), "Default");
final LeaderboardGroup leaderboardGroup;
if (createLeaderboardGroup) {
leaderboardGroup = validateAndAddLeaderboardGroup(event.getId(), event.getName(), event.getDescription(), /* leaderboardGroupDisplayNameParam */ null,
/* displayGroupsInReverseOrderParam */ false, /* leaderboardNamesParam */ null,
/* overallLeaderboardDiscardThresholdsParam */ null, /* overallLeaderboardScoringSchemeTypeParam */ null);
} else {
leaderboardGroup = null;
}
final RegattaLeaderboard leaderboard;
if (createRegatta) {
leaderboard = validateAndCreateRegatta(event.getName(), boatClassName,
/* scoringSchemeParam */ null, courseArea.getId(), /* buoyZoneRadiusInHullLengthsParam */ null,
/* useStartTimeInterferenceParam */ null, /* controlTrackingFromStartAndFinishTimesParam */ null,
/* rankingMetricParam */ null, /* leaderboardDiscardThresholdsParam */ null,
numberOfRacesParam, canBoatsOfCompetitorsChangePerRace, competitorRegistrationType, competitorRegistrationSecret);
if (leaderboardGroup != null) {
getService().apply(new UpdateLeaderboardGroup(leaderboardGroup.getName(), leaderboardGroup.getName(),
leaderboardGroup.getDescription(), leaderboardGroup.getDisplayName(),
Collections.singletonList(leaderboard.getName()),
leaderboardGroup.getOverallLeaderboard() == null ? null
: ((ThresholdBasedResultDiscardingRule) leaderboardGroup.getOverallLeaderboard()
.getResultDiscardingRule()).getDiscardIndexResultsStartingWithHowManyRaces(),
leaderboardGroup.getOverallLeaderboard() == null ? null
: leaderboardGroup.getOverallLeaderboard().getScoringScheme().getType()));
}
} else {
leaderboard = null;
}
return new Util.Triple<>(event, leaderboardGroup, leaderboard);
}
} else {
leaderboard = null;
};
try {
if (competitorRegistrationType == CompetitorRegistrationType.OPEN_UNMODERATED) {
UUID newTenantId = UUID.randomUUID();
UserGroup ownerGroup = getSecurityService().createUserGroup(newTenantId, eventName + "-owner");
getSecurityService().addUserToUserGroup(ownerGroup, getCurrentUser());
return getSecurityService().doWithTemporaryDefaultTenant(ownerGroup, doCreationAction);
} else {
return doCreationAction.run();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return new Util.Triple<>(event, leaderboardGroup, leaderboard);
}
private LeaderboardGroup validateAndAddLeaderboardGroup(UUID eventId, String leaderboardGroupName,
@@ -46,7 +46,6 @@ import com.sap.sailing.domain.tracking.TrackedRegatta;
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
import com.sap.sailing.server.impl.RacingEventServiceImpl;
import com.sap.sailing.server.operationaltransformation.CreateFlexibleLeaderboard;
import com.sap.sailing.server.operationaltransformation.RemoveAndUntrackRace;
import com.sap.sailing.server.operationaltransformation.RemoveEvent;
import com.sap.sailing.server.operationaltransformation.RemoveLeaderboard;
import com.sap.sailing.server.operationaltransformation.RemoveLeaderboardGroup;
@@ -120,8 +119,6 @@ public class RemoveLeaderboardTest {
public void testRaceLogOfRaceColumnInSeriesDetachedWhenRegattaIsRemoved() {
regatta.getRaceColumnByName(R1).setTrackedRace(defaultFleet, trackedRace);
assertEquals(1, Util.size(trackedRace.getAttachedRaceLogs()));
// removal of races is no longer done automatically, due to restrictions based on permission-vertical
server.apply(new RemoveAndUntrackRace(trackedRace.getRaceIdentifier()));
server.apply(new RemoveRegatta(new RegattaName(regatta.getName())));
assertTrue(Util.isEmpty(trackedRace.getAttachedRaceLogs()));
}
@@ -2503,11 +2503,23 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
@Override
public void removeRegatta(Regatta regatta) throws MalformedURLException, IOException, InterruptedException {
Set<RegattaLeaderboard> leaderboardsToRemove = new HashSet<>();
for (Leaderboard leaderboard : getLeaderboards().values()) {
if (leaderboard instanceof RegattaLeaderboard) {
RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboard;
if (regattaLeaderboard.getRegatta() == regatta) {
leaderboardsToRemove.add(regattaLeaderboard);
}
}
}
for (RegattaLeaderboard regattaLeaderboardToRemove : leaderboardsToRemove) {
removeLeaderboard(regattaLeaderboardToRemove.getName());
}
// avoid ConcurrentModificationException by copying the races to remove:
Set<RaceDefinition> racesToRemove = new HashSet<>();
Util.addAll(regatta.getAllRaces(), racesToRemove);
for (RaceDefinition race : racesToRemove) {
// FIXME can this be removed//moved to the removeRace part?
removeRace(regatta, race);
mongoObjectFactory.removeRegattaForRaceID(race.getName(), regatta);
persistentRegattasForRaceIDs.remove(race.getId().toString());
}
@@ -298,6 +298,11 @@ public class AdminConsolePanel extends HeaderPanel implements HandleTabSelectabl
return scrollPanel;
}
public void addToTabPanel(final HorizontalTabLayoutPanel tabPanel, RefreshableAdminConsolePanel panelToAdd,
String tabTitle) {
this.addToTabPanel(tabPanel, panelToAdd, tabTitle, new WildcardPermission(WildcardPermission.WILDCARD_TOKEN));
}
public void addToTabPanel(final HorizontalTabLayoutPanel tabPanel, RefreshableAdminConsolePanel panelToAdd, String tabTitle, WildcardPermission... requiresAnyOfThesePermissions) {
VerticalOrHorizontalTabLayoutPanel wrapper = new VerticalOrHorizontalTabLayoutPanel() {
@Override
@@ -375,6 +375,8 @@ public interface SecurityService extends ReplicableWithObjectInputStream<Replica
void checkCurrentUserDeletePermission(WithQualifiedObjectIdentifier object);
void checkCurrentUserDeletePermission(QualifiedObjectIdentifier object);
void checkCurrentUserExplicitPermissions(WithQualifiedObjectIdentifier object, HasPermissions.Action... actions);
/**
@@ -421,4 +423,6 @@ public interface SecurityService extends ReplicableWithObjectInputStream<Replica
*/
<T> T checkPermissionAndDeleteOwnershipForObjectRemoval(QualifiedObjectIdentifier identifier,
ActionWithResult<T> actionToDeleteObject);
<T> T doWithTemporaryDefaultTenant(UserGroup tenant, ActionWithResult<T> action);
}
@@ -165,6 +165,8 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
private ThreadLocal<Boolean> currentlyFillingFromInitialLoadOrApplyingOperationReceivedFromMaster = ThreadLocal.withInitial(() -> false);
private ThreadLocal<UserGroup> temporaryDefaultTenant = new InheritableThreadLocal<>();
// private TimerTask migrationCompleteCheckTask;
private static Ini shiroConfiguration;
@@ -359,10 +361,13 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
}
public UserGroup getDefaultTenantForUser(User user) {
UserGroup specificTenant = user.getDefaultTenant(ServerInfo.getName());
UserGroup specificTenant = temporaryDefaultTenant.get();
if (specificTenant == null) {
String defaultTenantName = getDefaultTenantNameForUsername(user.getName());
specificTenant = getUserGroupByName(defaultTenantName);
specificTenant = user.getDefaultTenant(ServerInfo.getName());
if (specificTenant == null) {
String defaultTenantName = getDefaultTenantNameForUsername(user.getName());
specificTenant = getUserGroupByName(defaultTenantName);
}
}
return specificTenant;
}
@@ -1890,6 +1895,11 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
SecurityUtils.getSubject().checkPermission(object.getType().getStringPermissionForObject(DefaultActions.DELETE, object));
}
@Override
public void checkCurrentUserDeletePermission(QualifiedObjectIdentifier identifier) {
SecurityUtils.getSubject().checkPermission(identifier.getStringPermission(DefaultActions.DELETE));
}
@Override
public void checkCurrentUserExplicitPermissions(WithQualifiedObjectIdentifier object, HasPermissions.Action... actions) {
if (object == null || actions.length == 0) {
@@ -1947,4 +1957,19 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
new Role(existingRole.getRoleDefinition(), destination, existingRole.getQualifiedForUser()));
}
}
@Override
public <T> T doWithTemporaryDefaultTenant(UserGroup tenant, ActionWithResult<T> action) {
final UserGroup previousValue = temporaryDefaultTenant.get();
temporaryDefaultTenant.set(tenant);
try {
return action.run();
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
temporaryDefaultTenant.set(previousValue);
}
}
}