mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-14 22:43:57 +00:00
bug4768 wip: as soon as the SecurityService becomes available, ensure
that all ownerships are explicit
This commit is contained in:
1 parent
f4c040dd3b
commit
7abb107ccb
3 files changed
+82
-14
No files matched your search
+2
-2
@@ -56,7 +56,7 @@ public abstract class AbstractServerReplicationTest extends com.sap.sse.replicat
|
||||
@Override public CompetitorAndBoatStore getCompetitorAndBoatStore() { return getBaseDomainFactory().getCompetitorAndBoatStore(); }
|
||||
};
|
||||
}, MediaDBFactory.INSTANCE.getMediaDB(mongoDBService), EmptyWindStore.INSTANCE, EmptySensorFixStore.INSTANCE, null, null, /* sailingNotificationService */ null,
|
||||
/* trackedRaceStatisticsCache */ null, /* restoreTrackedRaces */ false);
|
||||
/* trackedRaceStatisticsCache */ null, /* restoreTrackedRaces */ false, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -76,7 +76,7 @@ public abstract class AbstractServerReplicationTest extends com.sap.sse.replicat
|
||||
};
|
||||
}, MediaDBFactory.INSTANCE.getMediaDB(mongoDBService), EmptyWindStore.INSTANCE, EmptySensorFixStore.INSTANCE,
|
||||
/* serviceFinderFactory */ null, null, /* sailingNotificationService */ null,
|
||||
/* trackedRaceStatisticsCache */ null, /* restoreTrackedRaces */ false);
|
||||
/* trackedRaceStatisticsCache */ null, /* restoreTrackedRaces */ false, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import java.util.Dictionary;
|
||||
import java.util.HashSet;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -51,6 +52,7 @@ import com.sap.sse.mail.queue.impl.ExecutorMailQueue;
|
||||
import com.sap.sse.osgi.CachedOsgiTypeBasedServiceFinderFactory;
|
||||
import com.sap.sse.replication.Replicable;
|
||||
import com.sap.sse.security.PreferenceConverter;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sap.sse.util.ClearStateTestSupport;
|
||||
import com.sap.sse.util.ServiceTrackerFactory;
|
||||
|
||||
@@ -87,6 +89,8 @@ public class Activator implements BundleActivator {
|
||||
private SailingNotificationServiceImpl notificationService;
|
||||
|
||||
private ServiceTracker<MailService, MailService> mailServiceTracker;
|
||||
|
||||
private ServiceTracker<SecurityService, SecurityService> securityServiceTracker;
|
||||
|
||||
public Activator() {
|
||||
clearPersistentCompetitors = Boolean
|
||||
@@ -108,6 +112,7 @@ public class Activator implements BundleActivator {
|
||||
|
||||
trackedRegattaListener = new OSGiBasedTrackedRegattaListener(context);
|
||||
|
||||
|
||||
final TrackedRaceStatisticsCache trackedRaceStatisticsCache = new TrackedRaceStatisticsCacheImpl();
|
||||
registrations.add(context.registerService(TrackedRaceStatisticsCache.class.getName(), trackedRaceStatisticsCache, null));
|
||||
registrations.add(context.registerService(TrackedRegattaListener.class.getName(), trackedRaceStatisticsCache, null));
|
||||
@@ -118,9 +123,35 @@ public class Activator implements BundleActivator {
|
||||
// instead.
|
||||
serviceFinderFactory = new CachedOsgiTypeBasedServiceFinderFactory(context);
|
||||
|
||||
|
||||
// We use a tracker for this, as else we would assume that the SecurityService cannot be started before this
|
||||
// bundle, this way open() will fire instantly if the SecurityService already exists
|
||||
final CompletableFuture<SecurityService> securityServiceAvailable = new CompletableFuture<>();
|
||||
securityServiceTracker = new ServiceTracker<>(context, SecurityService.class,
|
||||
new ServiceTrackerCustomizer<SecurityService, SecurityService>() {
|
||||
|
||||
@Override
|
||||
public SecurityService addingService(ServiceReference<SecurityService> reference) {
|
||||
SecurityService securityService = context.getService(reference);
|
||||
securityServiceAvailable.complete(securityService);
|
||||
return securityService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modifiedService(ServiceReference<SecurityService> reference, SecurityService service) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removedService(ServiceReference<SecurityService> reference, SecurityService service) {
|
||||
}
|
||||
});
|
||||
|
||||
racingEventService = new RacingEventServiceImpl(clearPersistentCompetitors, serviceFinderFactory,
|
||||
trackedRegattaListener, notificationService, trackedRaceStatisticsCache, restoreTrackedRaces);
|
||||
trackedRegattaListener, notificationService, trackedRaceStatisticsCache, restoreTrackedRaces,
|
||||
securityServiceAvailable);
|
||||
notificationService.setRacingEventService(racingEventService);
|
||||
|
||||
securityServiceTracker.open();
|
||||
|
||||
masterDataImportClassLoaderServiceTracker = new ServiceTracker<MasterDataImportClassLoaderService, MasterDataImportClassLoaderService>(
|
||||
context, MasterDataImportClassLoaderService.class,
|
||||
@@ -209,6 +240,7 @@ public class Activator implements BundleActivator {
|
||||
notificationService.stop();
|
||||
mailQueue.stop();
|
||||
mailServiceTracker.close();
|
||||
securityServiceTracker.close();
|
||||
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||
mbs.unregisterMBean(mBeanName);
|
||||
}
|
||||
|
||||
+47
-11
@@ -28,6 +28,7 @@ import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
@@ -133,6 +134,7 @@ import com.sap.sailing.domain.common.impl.DataImportProgressImpl;
|
||||
import com.sap.sailing.domain.common.media.MediaTrack;
|
||||
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
|
||||
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
|
||||
import com.sap.sailing.domain.common.security.SecuredDomainType;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFix;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.common.tracking.SensorFix;
|
||||
@@ -284,6 +286,10 @@ import com.sap.sse.replication.OperationExecutionListener;
|
||||
import com.sap.sse.replication.OperationWithResult;
|
||||
import com.sap.sse.replication.ReplicationMasterDescriptor;
|
||||
import com.sap.sse.replication.impl.OperationWithResultWithIdWrapper;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sap.sse.security.shared.OwnershipAnnotation;
|
||||
import com.sap.sse.security.shared.QualifiedObjectIdentifier;
|
||||
import com.sap.sse.security.shared.UserGroup;
|
||||
import com.sap.sse.shared.media.ImageDescriptor;
|
||||
import com.sap.sse.shared.media.VideoDescriptor;
|
||||
import com.sap.sse.util.ClearStateTestSupport;
|
||||
@@ -503,8 +509,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
*/
|
||||
private final RaceChangeObserverForAnniversaryDetection raceChangeObserverForAnniversaryDetection;
|
||||
|
||||
private final PairingListTemplateFactory pairingListTemplateFactory = PairingListTemplateFactory.INSTANCE;
|
||||
|
||||
private final PairingListTemplateFactory pairingListTemplateFactory = PairingListTemplateFactory.INSTANCE;
|
||||
|
||||
/**
|
||||
* Providing the constructor parameters for a new {@link RacingEventServiceImpl} instance is a bit tricky
|
||||
* in some cases because containment and initialization order of some types is fairly tightly coupled.
|
||||
@@ -544,7 +550,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
}
|
||||
|
||||
public RacingEventServiceImpl(boolean clearPersistentCompetitorAndBoatStore, final TypeBasedServiceFinderFactory serviceFinderFactory, boolean restoreTrackedRaces) {
|
||||
this(clearPersistentCompetitorAndBoatStore, serviceFinderFactory, null, /* sailingNotificationService */ null, /* trackedRaceStatisticsCache */ null, restoreTrackedRaces);
|
||||
this(clearPersistentCompetitorAndBoatStore, serviceFinderFactory, null, /* sailingNotificationService */ null,
|
||||
/* trackedRaceStatisticsCache */ null, restoreTrackedRaces, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -552,20 +559,24 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
* be cleared before the service starts.
|
||||
*
|
||||
* @param clearPersistentCompetitorAndBoatStore
|
||||
* if <code>true</code>, the {@link PersistentCompetitorAndBoatStore} is created empty, with the corresponding
|
||||
* database collection cleared as well. Use with caution! When used with <code>false</code>, competitors and boats
|
||||
* created and stored during previous service executions will initially be loaded.
|
||||
* if <code>true</code>, the {@link PersistentCompetitorAndBoatStore} is created empty, with the
|
||||
* corresponding database collection cleared as well. Use with caution! When used with
|
||||
* <code>false</code>, competitors and boats created and stored during previous service executions will
|
||||
* initially be loaded.
|
||||
* @param sailingNotificationService
|
||||
* a notification service to call upon events worth notifying users about, or {@code null} if no
|
||||
* notification service is available, e.g., in test set-ups
|
||||
* @param trackedRaceStatisticsCache
|
||||
* a cache that gives access to detailed statistics about TrackedRaces. If <code>null</code>, no detailed
|
||||
* statistics about TrackedRaces will be calculated.
|
||||
* @param securityServiceTracker
|
||||
* @param securityServiceAvailable
|
||||
*/
|
||||
public RacingEventServiceImpl(boolean clearPersistentCompetitorAndBoatStore,
|
||||
final TypeBasedServiceFinderFactory serviceFinderFactory, TrackedRegattaListenerManager trackedRegattaListener,
|
||||
SailingNotificationService sailingNotificationService,
|
||||
TrackedRaceStatisticsCache trackedRaceStatisticsCache, boolean restoreTrackedRaces) {
|
||||
TrackedRaceStatisticsCache trackedRaceStatisticsCache, boolean restoreTrackedRaces,
|
||||
CompletableFuture<SecurityService> securityServiceAvailable) {
|
||||
this((final RaceLogResolver raceLogResolver) -> {
|
||||
return new ConstructorParameters() {
|
||||
private final MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE
|
||||
@@ -595,7 +606,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
}
|
||||
};
|
||||
}, MediaDBFactory.INSTANCE.getDefaultMediaDB(), null, null, serviceFinderFactory, trackedRegattaListener,
|
||||
sailingNotificationService, trackedRaceStatisticsCache, restoreTrackedRaces);
|
||||
sailingNotificationService, trackedRaceStatisticsCache, restoreTrackedRaces,
|
||||
securityServiceAvailable);
|
||||
}
|
||||
|
||||
private RacingEventServiceImpl(final boolean clearPersistentCompetitorStore, WindStore windStore,
|
||||
@@ -629,7 +641,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
}
|
||||
};
|
||||
}, MediaDBFactory.INSTANCE.getDefaultMediaDB(), windStore, sensorFixStore, serviceFinderFactory, null,
|
||||
sailingNotificationService, /* trackedRaceStatisticsCache */ null, restoreTrackedRaces);
|
||||
sailingNotificationService, /* trackedRaceStatisticsCache */ null, restoreTrackedRaces, null);
|
||||
}
|
||||
|
||||
public RacingEventServiceImpl(final DomainObjectFactory domainObjectFactory, MongoObjectFactory mongoObjectFactory,
|
||||
@@ -657,7 +669,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
}
|
||||
};
|
||||
}, mediaDB, windStore, sensorFixStore, null, null, /* sailingNotificationService */ null,
|
||||
/* trackedRaceStatisticsCache */ null, restoreTrackedRaces);
|
||||
/* trackedRaceStatisticsCache */ null, restoreTrackedRaces, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -683,12 +695,16 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
* {@code false}, all restore information is
|
||||
* {@link MongoObjectFactory#removeAllConnectivityParametersForRacesToRestore() cleared} from the
|
||||
* database, and the server starts out with an empty list of tracked races.
|
||||
* @param securityServiceAvailable
|
||||
* will complete as soon as the securityServiceTracker is able to provide a SecurityService, NEVER hold a
|
||||
* reference to the result of this, as it might become invalid if bundles are replaced/ restarted
|
||||
*/
|
||||
public RacingEventServiceImpl(Function<RaceLogResolver, ConstructorParameters> constructorParametersProvider,
|
||||
MediaDB mediaDb, final WindStore windStore, final SensorFixStore sensorFixStore,
|
||||
TypeBasedServiceFinderFactory serviceFinderFactory, TrackedRegattaListenerManager trackedRegattaListener,
|
||||
SailingNotificationService sailingNotificationService,
|
||||
TrackedRaceStatisticsCache trackedRaceStatisticsCache, boolean restoreTrackedRaces) {
|
||||
TrackedRaceStatisticsCache trackedRaceStatisticsCache, boolean restoreTrackedRaces,
|
||||
CompletableFuture<SecurityService> securityServiceAvailable) {
|
||||
logger.info("Created " + this);
|
||||
this.numberOfTrackedRacesRestored = new AtomicInteger();
|
||||
this.scoreCorrectionListenersByLeaderboard = new ConcurrentHashMap<>();
|
||||
@@ -803,6 +819,10 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
new QuarterChecker(), new SameDigitChecker());
|
||||
raceChangeObserverForAnniversaryDetection = new RaceChangeObserverForAnniversaryDetection(anniversaryRaceDeterminator);
|
||||
this.trackedRegattaListener.addListener(raceChangeObserverForAnniversaryDetection);
|
||||
|
||||
if (securityServiceAvailable != null) {
|
||||
securityServiceAvailable.thenAccept(t -> ensureOwnerships(t));
|
||||
}
|
||||
}
|
||||
|
||||
private void restoreTrackedRaces() {
|
||||
@@ -893,6 +913,20 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
return domainObjectFactory;
|
||||
}
|
||||
|
||||
private void ensureOwnerships(SecurityService securityService) {
|
||||
for (Event event : eventsById.values()) {
|
||||
QualifiedObjectIdentifier eventIdentifier = SecuredDomainType.EVENT
|
||||
.getQualifiedObjectIdentifier(event.getId().toString());
|
||||
OwnershipAnnotation owner = securityService.getOwnership(eventIdentifier);
|
||||
UserGroup defaultTenant = securityService.getDefaultTenant();
|
||||
if (owner == null) {
|
||||
logger.info("Setting ownership for " + eventIdentifier + " to " + defaultTenant);
|
||||
securityService.setOwnership(eventIdentifier, null, defaultTenant,
|
||||
event.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadRaceIDToRegattaAssociations() {
|
||||
persistentRegattasForRaceIDs.putAll(domainObjectFactory.loadRaceIDToRegattaAssociations(this));
|
||||
}
|
||||
@@ -915,12 +949,14 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
}
|
||||
|
||||
private Iterable<Pair<Event, Boolean>> loadStoredEvents() {
|
||||
|
||||
Iterable<Pair<Event, Boolean>> loadedEventsWithRequireStoreFlag = domainObjectFactory.loadAllEvents();
|
||||
for (Pair<Event, Boolean> eventAndFlag : loadedEventsWithRequireStoreFlag) {
|
||||
Event event = eventAndFlag.getA();
|
||||
if (event.getId() != null)
|
||||
eventsById.put(event.getId(), event);
|
||||
}
|
||||
|
||||
return loadedEventsWithRequireStoreFlag;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user