mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-13 22:15:26 +00:00
Merge branch 'permission-vertical' of ssh://trac@sapsailing.com/home/trac/git into permission-vertical
This commit is contained in:
commit
7b41c741ce
18 files changed
+449
-51
No files matched your search
@@ -97,12 +97,6 @@ extra=''
|
||||
parallelexecution=0
|
||||
p2local=0
|
||||
|
||||
export max_user_watches=`cat /proc/sys/fs/inotify/max_user_watches`
|
||||
echo "max User Watches: $max_user_watches"
|
||||
echo "trying to set max User Watches to 16384"
|
||||
sysctl fs.inotify.max_user_watches=16384
|
||||
sysctl -p
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "buildAndUpdateProduct [-b -u -g -t -a -r -o -c -p -v -m <config> -n <package> -l <port> -x <gwt-workers> -j <test-package>] [build|install|all|hot-deploy|remote-deploy|local-deploy|release]"
|
||||
echo ""
|
||||
@@ -197,7 +191,7 @@ echo TMP will be used for java.io.tmpdir and is $TMP
|
||||
if [ "$TMP" = "" ]; then
|
||||
export TMP=/tmp
|
||||
fi
|
||||
extra="${extra} -Dgwt.workers=${GWT_WORKERS} -Djava.io.tmpdir=$TMP -Dgwt.watchFileChanges=false"
|
||||
extra="${extra} -Dgwt.workers=${GWT_WORKERS} -Djava.io.tmpdir=$TMP"
|
||||
|
||||
shift $((OPTIND-1))
|
||||
|
||||
|
||||
+2
-1
@@ -5,11 +5,12 @@ import java.io.Serializable;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.MappableToDevice;
|
||||
import com.sap.sse.common.Color;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.security.shared.SecuredObject;
|
||||
|
||||
/**
|
||||
* Equality and hash code are based on the {@link #getIdAsString() ID} and all contained attributes like name, shortName, email, etc.
|
||||
*/
|
||||
public interface CompetitorDTO extends Serializable, MappableToDevice {
|
||||
public interface CompetitorDTO extends Serializable, MappableToDevice, SecuredObject {
|
||||
|
||||
String getTwoLetterIsoCountryCode();
|
||||
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ import java.io.Serializable;
|
||||
|
||||
import com.sap.sse.common.Color;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.security.shared.NamedDTO;
|
||||
import com.sap.sse.security.shared.NamedSecuredObjectDTO;
|
||||
|
||||
/**
|
||||
* Equality and hash code are based on the {@link #getIdAsString() ID}, the {@link #getSailID() sail number}, the
|
||||
@@ -15,7 +15,7 @@ import com.sap.sse.security.shared.NamedDTO;
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serializable {
|
||||
public class CompetitorDTOImpl extends NamedSecuredObjectDTO implements CompetitorDTO, Serializable {
|
||||
private static final long serialVersionUID = 3019126418065082622L;
|
||||
private String countryName;
|
||||
private String twoLetterIsoCountryCode;
|
||||
|
||||
+2
-1
@@ -2,6 +2,7 @@ package com.sap.sailing.domain.common.dto;
|
||||
|
||||
import com.sap.sse.common.Color;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.security.shared.NamedSecuredObjectDTO;
|
||||
|
||||
/**
|
||||
* Equality and hash code are based on the index pointing into a previous leaderboard's competitors list.
|
||||
@@ -9,7 +10,7 @@ import com.sap.sse.common.Duration;
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public class PreviousCompetitorDTOImpl implements CompetitorDTO {
|
||||
public class PreviousCompetitorDTOImpl extends NamedSecuredObjectDTO implements CompetitorDTO {
|
||||
private static final long serialVersionUID = 8820028699103040805L;
|
||||
private int indexInPreviousCompetitorList;
|
||||
|
||||
|
||||
+10
-2
@@ -66,15 +66,23 @@ public class SecuredDomainType extends HasPermissionsImpl {
|
||||
*/
|
||||
public static final HasPermissions TRACKED_RACE = new SecuredDomainType("TRACKED_RACE");
|
||||
|
||||
public static enum CompetitorAndBoatActions implements Action {
|
||||
READ_PUBLIC, READ_PRIVATE, LIST;
|
||||
|
||||
private static final Action[] ALL_ACTIONS = new Action[] { READ_PUBLIC, READ_PRIVATE, LIST,
|
||||
DefaultActions.CREATE, DefaultActions.UPDATE, DefaultActions.CHANGE_OWNERSHIP,
|
||||
DefaultActions.CHANGE_ACL };
|
||||
};
|
||||
|
||||
/**
|
||||
* type relative identifier is the competitor ID's string representation
|
||||
*/
|
||||
public static final HasPermissions COMPETITOR = new SecuredDomainType("COMPETITOR");
|
||||
public static final HasPermissions COMPETITOR = new SecuredDomainType("COMPETITOR", CompetitorAndBoatActions.ALL_ACTIONS);
|
||||
|
||||
/**
|
||||
* type relative identifier is the boat ID's string representation
|
||||
*/
|
||||
public static final HasPermissions BOAT = new SecuredDomainType("BOAT");
|
||||
public static final HasPermissions BOAT = new SecuredDomainType("BOAT", CompetitorAndBoatActions.ALL_ACTIONS);
|
||||
|
||||
/**
|
||||
* type-relative identifier is the media track's "DB ID"
|
||||
|
||||
@@ -163,7 +163,6 @@
|
||||
<warSourceDirectory>${basedir}/src/main/resources</warSourceDirectory>
|
||||
<!-- Uncomment the following to obtain details split-point reports
|
||||
<compileReport>true</compileReport> <detailedSoyc>true</detailedSoyc> -->
|
||||
<extraJvmArgs>-Dgwt.watchFileChanges=false -Xmx8192m</extraJvmArgs>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
|
||||
+6
@@ -950,4 +950,10 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS
|
||||
void setDefaultTenantForCurrentServer(String tennant);
|
||||
|
||||
List<String> getPossibleTennants();
|
||||
|
||||
void updateGroupOwnerForEventHierarchy(UUID eventId, UUID newGroupOwnerId, String newGroupNameToCreate,
|
||||
boolean updateCompetitors, boolean updateBoats);
|
||||
|
||||
void updateGroupOwnerForLeaderboardGroupHierarchy(UUID leaderboardGroupId, UUID newGroupOwnerId,
|
||||
String newGroupNameToCreate, boolean updateCompetitors, boolean updateBoats);
|
||||
}
|
||||
+6
@@ -1049,4 +1049,10 @@ public interface SailingServiceAsync extends ServerInfoRetriever, FileStorageMan
|
||||
* gets a (possibly imcomplete) list of available tennants to choose from.
|
||||
*/
|
||||
void getPossibleTennants(AsyncCallback<List<String>> asyncCallback);
|
||||
|
||||
void updateGroupOwnerForEventHierarchy(UUID eventId, UUID newGroupOwnerId, String newGroupNameToCreate,
|
||||
boolean updateCompetitors, boolean updateBoats, AsyncCallback<Void> callback);
|
||||
|
||||
void updateGroupOwnerForLeaderboardGroupHierarchy(UUID leaderboardGroupId, UUID newGroupOwnerId,
|
||||
String newGroupNameToCreate, boolean updateCompetitors, boolean updateBoats, AsyncCallback<Void> callback);
|
||||
}
|
||||
+132
-27
@@ -469,6 +469,8 @@ import com.sap.sailing.manage2sail.RegattaResultDescriptor;
|
||||
import com.sap.sailing.resultimport.ResultUrlProvider;
|
||||
import com.sap.sailing.resultimport.ResultUrlRegistry;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sailing.server.hierarchy.SailingHierarchyOwnershipUpdater;
|
||||
import com.sap.sailing.server.hierarchy.SailingHierarchyOwnershipUpdater.GroupOwnerUpdateStrategy;
|
||||
import com.sap.sailing.server.masterdata.MasterDataImporter;
|
||||
import com.sap.sailing.server.operationaltransformation.AddColumnToLeaderboard;
|
||||
import com.sap.sailing.server.operationaltransformation.AddColumnToSeries;
|
||||
@@ -591,10 +593,13 @@ import com.sap.sse.security.ActionWithResult;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sap.sse.security.SessionUtils;
|
||||
import com.sap.sse.security.shared.HasPermissions.DefaultActions;
|
||||
import com.sap.sse.security.shared.OwnershipAnnotation;
|
||||
import com.sap.sse.security.shared.QualifiedObjectIdentifier;
|
||||
import com.sap.sse.security.shared.RoleDefinition;
|
||||
import com.sap.sse.security.shared.RoleImpl;
|
||||
import com.sap.sse.security.shared.User;
|
||||
import com.sap.sse.security.shared.UserGroup;
|
||||
import com.sap.sse.security.shared.UserGroupManagementException;
|
||||
import com.sap.sse.security.shared.WildcardPermission;
|
||||
import com.sap.sse.security.shared.impl.SecuredSecurityTypes;
|
||||
import com.sap.sse.security.shared.impl.SecuredSecurityTypes.ServerActions;
|
||||
@@ -1245,6 +1250,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
List<CompetitorDTO> result = new ArrayList<>();
|
||||
for (Competitor c : iterable) {
|
||||
CompetitorDTO competitorDTO = baseDomainFactory.convertToCompetitorDTO(c);
|
||||
SecurityDTOUtil.addSecurityInformation(getSecurityService(), competitorDTO, c.getIdentifier());
|
||||
result.add(competitorDTO);
|
||||
}
|
||||
return result;
|
||||
@@ -5479,7 +5485,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
}
|
||||
|
||||
private CompetitorWithBoat addOrUpdateCompetitorWithBoatInternal(CompetitorWithBoatDTO competitor) throws URISyntaxException {
|
||||
CompetitorWithBoat result;
|
||||
final CompetitorWithBoat result;
|
||||
CompetitorWithBoat existingCompetitor = getService().getCompetitorAndBoatStore().getExistingCompetitorWithBoatByIdAsString(competitor.getIdAsString());
|
||||
Nationality nationality = (competitor.getThreeLetterIocCountryCode() == null || competitor.getThreeLetterIocCountryCode().isEmpty()) ? null :
|
||||
getBaseDomainFactory().getOrCreateNationality(competitor.getThreeLetterIocCountryCode());
|
||||
@@ -5490,13 +5496,23 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
DynamicTeam team = new TeamImpl(competitor.getName() + " team", Collections.singleton(sailor), null);
|
||||
// new boat
|
||||
DynamicBoat boat = (DynamicBoat) addOrUpdateBoatInternal(competitor.getBoat());
|
||||
result = getBaseDomainFactory().getOrCreateCompetitorWithBoat(competitorUUID, competitor.getName(), competitor.getShortName(),
|
||||
competitor.getColor(), competitor.getEmail(),
|
||||
competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), team,
|
||||
competitor.getTimeOnTimeFactor(),
|
||||
competitor.getTimeOnDistanceAllowancePerNauticalMile(), competitor.getSearchTag(), boat);
|
||||
|
||||
final UUID competitorUuid = UUID.randomUUID();
|
||||
result = getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
|
||||
SecuredDomainType.COMPETITOR, competitorUuid.toString(), competitor.getName(),
|
||||
new ActionWithResult<CompetitorWithBoat>() {
|
||||
@Override
|
||||
public CompetitorWithBoat run() throws Exception {
|
||||
return getBaseDomainFactory().getCompetitorAndBoatStore().getOrCreateCompetitorWithBoat(
|
||||
competitorUUID, competitor.getName(), competitor.getShortName(),
|
||||
competitor.getColor(), competitor.getEmail(),
|
||||
competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()),
|
||||
team, competitor.getTimeOnTimeFactor(),
|
||||
competitor.getTimeOnDistanceAllowancePerNauticalMile(), competitor.getSearchTag(),
|
||||
boat);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
SecurityUtils.getSubject().checkPermission(SecuredDomainType.COMPETITOR.getStringPermissionForObjects(DefaultActions.UPDATE, competitor.getIdAsString()));
|
||||
Competitor updatedCompetitor = getService().apply(
|
||||
new UpdateCompetitor(competitor.getIdAsString(), competitor.getName(), competitor.getShortName(),
|
||||
competitor.getColor(), competitor.getEmail(), nationality,
|
||||
@@ -5513,29 +5529,39 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
|
||||
|
||||
private Competitor addOrUpdateCompetitorWithoutBoatInternal(CompetitorDTO competitor) throws URISyntaxException {
|
||||
Competitor result;
|
||||
Competitor existingCompetitor = getService().getCompetitorAndBoatStore().getExistingCompetitorByIdAsString(competitor.getIdAsString());
|
||||
Nationality nationality = (competitor.getThreeLetterIocCountryCode() == null || competitor.getThreeLetterIocCountryCode().isEmpty()) ? null :
|
||||
getBaseDomainFactory().getOrCreateNationality(competitor.getThreeLetterIocCountryCode());
|
||||
final Competitor result;
|
||||
Competitor existingCompetitor = getService().getCompetitorAndBoatStore()
|
||||
.getExistingCompetitorByIdAsString(competitor.getIdAsString());
|
||||
Nationality nationality = (competitor.getThreeLetterIocCountryCode() == null
|
||||
|| competitor.getThreeLetterIocCountryCode().isEmpty()) ? null
|
||||
: getBaseDomainFactory().getOrCreateNationality(competitor.getThreeLetterIocCountryCode());
|
||||
if (competitor.getIdAsString() == null || competitor.getIdAsString().isEmpty() || existingCompetitor == null) {
|
||||
// new competitor
|
||||
UUID competitorUUID = UUID.randomUUID();
|
||||
DynamicPerson sailor = new PersonImpl(competitor.getName(), nationality, null, null);
|
||||
DynamicTeam team = new TeamImpl(competitor.getName() + " team", Collections.singleton(sailor), null);
|
||||
result = getBaseDomainFactory().getOrCreateCompetitor(competitorUUID, competitor.getName(), competitor.getShortName(),
|
||||
competitor.getColor(), competitor.getEmail(),
|
||||
competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), team,
|
||||
competitor.getTimeOnTimeFactor(),
|
||||
competitor.getTimeOnDistanceAllowancePerNauticalMile(), competitor.getSearchTag());
|
||||
} else {
|
||||
result = getService().apply(
|
||||
new UpdateCompetitor(competitor.getIdAsString(), competitor.getName(), competitor.getShortName(),
|
||||
competitor.getColor(), competitor.getEmail(), nationality,
|
||||
competitor.getImageURL() == null ? null : new URI(competitor.getImageURL()),
|
||||
result = getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
|
||||
SecuredDomainType.COMPETITOR, competitorUUID.toString(), competitor.getName(),
|
||||
new ActionWithResult<Competitor>() {
|
||||
|
||||
@Override
|
||||
public Competitor run() throws Exception {
|
||||
return getBaseDomainFactory().getOrCreateCompetitor(competitorUUID, competitor.getName(),
|
||||
competitor.getShortName(), competitor.getColor(), competitor.getEmail(),
|
||||
competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()),
|
||||
competitor.getTimeOnTimeFactor(),
|
||||
competitor.getTimeOnDistanceAllowancePerNauticalMile(),
|
||||
competitor.getSearchTag()));
|
||||
team, competitor.getTimeOnTimeFactor(),
|
||||
competitor.getTimeOnDistanceAllowancePerNauticalMile(), competitor.getSearchTag());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
SecurityUtils.getSubject().checkPermission(SecuredDomainType.COMPETITOR
|
||||
.getStringPermissionForObjects(DefaultActions.UPDATE, competitor.getIdAsString()));
|
||||
result = getService().apply(new UpdateCompetitor(competitor.getIdAsString(), competitor.getName(),
|
||||
competitor.getShortName(), competitor.getColor(), competitor.getEmail(), nationality,
|
||||
competitor.getImageURL() == null ? null : new URI(competitor.getImageURL()),
|
||||
competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()),
|
||||
competitor.getTimeOnTimeFactor(), competitor.getTimeOnDistanceAllowancePerNauticalMile(),
|
||||
competitor.getSearchTag()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -5593,10 +5619,20 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
// new boat
|
||||
UUID boatUUID = UUID.randomUUID();
|
||||
BoatClass boatClass = getBaseDomainFactory().getOrCreateBoatClass(boat.getBoatClass().getName());
|
||||
result = getBaseDomainFactory().getOrCreateBoat(boatUUID, boat.getName(), boatClass, boat.getSailId(), boat.getColor());
|
||||
result = getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
|
||||
SecuredDomainType.BOAT, boatUUID.toString(), boat.getName(), new ActionWithResult<Boat>() {
|
||||
|
||||
@Override
|
||||
public Boat run() throws Exception {
|
||||
return getBaseDomainFactory().getOrCreateBoat(boatUUID, boat.getName(), boatClass,
|
||||
boat.getSailId(), boat.getColor());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
result = getService().apply(
|
||||
new UpdateBoat(boat.getIdAsString(), boat.getName(), boat.getColor(), boat.getSailId()));
|
||||
SecurityUtils.getSubject().checkPermission(
|
||||
SecuredDomainType.BOAT.getStringPermissionForObjects(DefaultActions.UPDATE, boat.getIdAsString()));
|
||||
result = getService()
|
||||
.apply(new UpdateBoat(boat.getIdAsString(), boat.getName(), boat.getColor(), boat.getSailId()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -8519,4 +8555,73 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateGroupOwnerForEventHierarchy(UUID eventId, UUID newGroupOwnerId, String newGroupNameToCreate, boolean updateCompetitors,
|
||||
boolean updateBoats) {
|
||||
Event event = getService().getEvent(eventId);
|
||||
UserGroup groupOwnerToSet = getSecurityService().getUserGroup(newGroupOwnerId);
|
||||
if (event != null && groupOwnerToSet != null) {
|
||||
createOwnershipUpdater(newGroupOwnerId, newGroupNameToCreate, updateCompetitors,
|
||||
updateBoats).updateGroupOwnershipForEventHierarchy(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateGroupOwnerForLeaderboardGroupHierarchy(UUID leaderboardGroupId, UUID newGroupOwnerId, String newGroupNameToCreate,
|
||||
boolean updateCompetitors, boolean updateBoats) {
|
||||
LeaderboardGroup leaderboardGroup = getService().getLeaderboardGroupByID(leaderboardGroupId);
|
||||
UserGroup groupOwnerToSet = getSecurityService().getUserGroup(newGroupOwnerId);
|
||||
if (leaderboardGroup != null && groupOwnerToSet != null) {
|
||||
createOwnershipUpdater(newGroupOwnerId, newGroupNameToCreate, updateCompetitors,
|
||||
updateBoats).updateGroupOwnershipForLeaderboardGroupHierarchy(leaderboardGroup);
|
||||
}
|
||||
}
|
||||
|
||||
private SailingHierarchyOwnershipUpdater createOwnershipUpdater( UUID newGroupOwnerId, String newGroupNameToCreate, boolean updateCompetitors,
|
||||
boolean updateBoats) {
|
||||
final GroupOwnerUpdateStrategy updateStrategy;
|
||||
if (newGroupOwnerId != null) {
|
||||
final UserGroup groupOwnerToSet = getSecurityService().getUserGroup(newGroupOwnerId);
|
||||
if (groupOwnerToSet == null) {
|
||||
throw new RuntimeException("User group does not exist");
|
||||
}
|
||||
updateStrategy = new GroupOwnerUpdateStrategy() {
|
||||
@Override
|
||||
public boolean needsUpdate(QualifiedObjectIdentifier identifier, OwnershipAnnotation currentOwnership) {
|
||||
return currentOwnership == null || !groupOwnerToSet.equals(currentOwnership.getAnnotation().getTenantOwner());
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserGroup getNewGroupOwner() {
|
||||
return groupOwnerToSet;
|
||||
}
|
||||
};
|
||||
} else if (newGroupNameToCreate != null && ! newGroupNameToCreate.isEmpty()) {
|
||||
updateStrategy = new GroupOwnerUpdateStrategy() {
|
||||
private UserGroup groupOwnerToSet;
|
||||
|
||||
@Override
|
||||
public boolean needsUpdate(QualifiedObjectIdentifier identifier, OwnershipAnnotation currentOwnership) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserGroup getNewGroupOwner() {
|
||||
if (groupOwnerToSet != null) {
|
||||
try {
|
||||
groupOwnerToSet = getSecurityService().createUserGroup(UUID.randomUUID(), newGroupNameToCreate);
|
||||
} catch (UserGroupManagementException e) {
|
||||
throw new RuntimeException("Could not create user group");
|
||||
}
|
||||
}
|
||||
return groupOwnerToSet;
|
||||
}
|
||||
};
|
||||
} else {
|
||||
throw new RuntimeException("No user group given");
|
||||
}
|
||||
return new SailingHierarchyOwnershipUpdater(getService(), getSecurityService(), updateStrategy, updateCompetitors,
|
||||
updateBoats);
|
||||
}
|
||||
}
|
||||
+32
-8
@@ -124,6 +124,7 @@ 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.SecurityService;
|
||||
import com.sap.sse.security.shared.HasPermissions.DefaultActions;
|
||||
import com.sap.sse.security.shared.User;
|
||||
@@ -357,12 +358,22 @@ public class RegattasResource extends AbstractSailingServerResource {
|
||||
getService().getBaseDomainFactory().getOrCreateNationality(nationalityThreeLetterIOCCode),
|
||||
/* dateOfBirth */ null, /* description */ null)),
|
||||
/* coach */ null);
|
||||
final CompetitorWithBoat competitor = getService().getCompetitorAndBoatStore()
|
||||
.getOrCreateCompetitorWithBoat(UUID.randomUUID(), name, /* shortName */ null,
|
||||
/* displayColor */ null, email, /* flagImageURI */ null, team, timeOnTimeFactor,
|
||||
timeOnDistanceAllowancePerNauticalMileAsMillis == null ? null
|
||||
: new MillisecondsDurationImpl(timeOnDistanceAllowancePerNauticalMileAsMillis),
|
||||
searchTag, boat);
|
||||
final UUID competitorUuid = UUID.randomUUID();
|
||||
final CompetitorWithBoat competitor = getSecurityService()
|
||||
.setOwnershipCheckPermissionForObjectCreationAndRevertOnError(SecuredDomainType.COMPETITOR,
|
||||
competitorUuid.toString(), name, new ActionWithResult<CompetitorWithBoat>() {
|
||||
@Override
|
||||
public CompetitorWithBoat run() throws Exception {
|
||||
return getService().getCompetitorAndBoatStore().getOrCreateCompetitorWithBoat(
|
||||
UUID.randomUUID(), name, /* shortName */ null, /* displayColor */ null,
|
||||
email, /* flagImageURI */ null, team, timeOnTimeFactor,
|
||||
timeOnDistanceAllowancePerNauticalMileAsMillis == null ? null
|
||||
: new MillisecondsDurationImpl(
|
||||
timeOnDistanceAllowancePerNauticalMileAsMillis),
|
||||
searchTag, boat);
|
||||
}
|
||||
});
|
||||
|
||||
regatta.registerCompetitor(competitor);
|
||||
response = Response.ok(CompetitorJsonSerializer.create().serialize(competitor).toJSONString())
|
||||
.header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build();
|
||||
@@ -386,12 +397,25 @@ public class RegattasResource extends AbstractSailingServerResource {
|
||||
} else {
|
||||
response = createAndAddCompetitor(regattaName, nationalityThreeLetterIOCCode, timeOnTimeFactor,
|
||||
timeOnDistanceAllowancePerNauticalMileAsMillis, searchTag, competitorName, competitorEmail,
|
||||
shortName -> new BoatImpl(UUID.randomUUID(), shortName, getService().getBaseDomainFactory()
|
||||
.getOrCreateBoatClass(boatClassName, /* typicallyStartsUpwind */ true), sailId));
|
||||
shortName -> createBoat(shortName, boatClassName, sailId));
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
private DynamicBoat createBoat(String name, String boatClassName, String sailId) {
|
||||
final UUID boatUUID = UUID.randomUUID();
|
||||
DynamicBoat boat = getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
|
||||
SecuredDomainType.BOAT, boatUUID.toString(), name, new ActionWithResult<DynamicBoat>() {
|
||||
|
||||
@Override
|
||||
public DynamicBoat run() throws Exception {
|
||||
return new BoatImpl(boatUUID, name, getService().getBaseDomainFactory()
|
||||
.getOrCreateBoatClass(boatClassName, /* typicallyStartsUpwind */ true), sailId);
|
||||
}
|
||||
});
|
||||
return boat;
|
||||
}
|
||||
|
||||
@POST
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
@Path("{regattaname}/competitors/createandaddwithboat")
|
||||
|
||||
@@ -43,6 +43,7 @@ Require-Bundle: com.sap.sailing.domain,
|
||||
com.sap.sse.security.common
|
||||
Bundle-ClassPath: .
|
||||
Export-Package: com.sap.sailing.server,
|
||||
com.sap.sailing.server.hierarchy,
|
||||
com.sap.sailing.server.impl;
|
||||
x-friends:="com.sap.sailing.mongodb.test,
|
||||
com.sap.sailing.server.test,
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.sap.sailing.server.hierarchy;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
|
||||
|
||||
public interface EventHierarchyVisitor {
|
||||
|
||||
void visit(LeaderboardGroup leaderboardGroup);
|
||||
|
||||
void visit(Leaderboard leaderboard, Set<LeaderboardGroup> leaderboardGroups);
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package com.sap.sailing.server.hierarchy;
|
||||
|
||||
import com.sap.sailing.domain.base.Event;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
|
||||
public interface LeaderboardGroupHierarchyVisitor {
|
||||
|
||||
void visit(Event event);
|
||||
|
||||
void visit(Leaderboard leaderboard);
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.sap.sailing.server.hierarchy;
|
||||
|
||||
import com.sap.sailing.domain.base.Boat;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
|
||||
public interface LeaderboardHierarchyVisitor {
|
||||
|
||||
void visit(TrackedRace race);
|
||||
|
||||
void visit(Competitor competitor);
|
||||
|
||||
void visit(Boat boat);
|
||||
|
||||
}
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
package com.sap.sailing.server.hierarchy;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
|
||||
import com.sap.sailing.domain.base.Boat;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.Event;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sap.sse.security.shared.HasPermissions.DefaultActions;
|
||||
import com.sap.sse.security.shared.OwnershipAnnotation;
|
||||
import com.sap.sse.security.shared.QualifiedObjectIdentifier;
|
||||
import com.sap.sse.security.shared.User;
|
||||
import com.sap.sse.security.shared.UserGroup;
|
||||
import com.sap.sse.security.shared.WildcardPermission;
|
||||
|
||||
/**
|
||||
* Encapsulates the logic to ensure consistency of group owners in the sailing domain object hierarchy.
|
||||
*/
|
||||
public class SailingHierarchyOwnershipUpdater {
|
||||
|
||||
public interface GroupOwnerUpdateStrategy {
|
||||
boolean needsUpdate(QualifiedObjectIdentifier identifier, OwnershipAnnotation currentOwnership);
|
||||
|
||||
UserGroup getNewGroupOwner();
|
||||
}
|
||||
|
||||
private final RacingEventService service;
|
||||
private final SecurityService securityService;
|
||||
private final GroupOwnerUpdateStrategy updateStrategy;
|
||||
private final boolean updateCompetitors;
|
||||
private final boolean updateBoats;
|
||||
private final Set<QualifiedObjectIdentifier> objectsToUpdateOwnershipsFor;
|
||||
|
||||
public SailingHierarchyOwnershipUpdater(final RacingEventService service, SecurityService securityService,
|
||||
final GroupOwnerUpdateStrategy updateStrategy, final boolean updateCompetitors, final boolean updateBoats) {
|
||||
this.service = service;
|
||||
this.securityService = securityService;
|
||||
this.updateStrategy = updateStrategy;
|
||||
this.updateCompetitors = updateCompetitors;
|
||||
this.updateBoats = updateBoats;
|
||||
objectsToUpdateOwnershipsFor = new HashSet<>();
|
||||
}
|
||||
|
||||
public void updateGroupOwnershipForEventHierarchy(Event event) {
|
||||
updateGroupOwnershipForEventHierarchyInternal(event);
|
||||
commitChanges();
|
||||
}
|
||||
|
||||
private void updateGroupOwnershipForEventHierarchyInternal(Event event) {
|
||||
updateGroupOwner(event.getIdentifier());
|
||||
SailingHierarchyWalker.walkFromEvent(event, false, new EventHierarchyVisitor() {
|
||||
@Override
|
||||
public void visit(Leaderboard leaderboard, Set<LeaderboardGroup> leaderboardGroups) {
|
||||
updateGroupOwnershipForLeaderboardHierarchy(leaderboard);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(LeaderboardGroup leaderboardGroup) {
|
||||
// No LeaderboardGroups with overall leaderboard are visited -> no infinite recursion occurs
|
||||
updateGroupOwnershipForLeaderboardGroupHierarchyInternal(leaderboardGroup);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void updateGroupOwnershipForLeaderboardGroupHierarchy(LeaderboardGroup leaderboardGroup) {
|
||||
updateGroupOwnershipForLeaderboardGroupHierarchyInternal(leaderboardGroup);
|
||||
commitChanges();
|
||||
}
|
||||
|
||||
public void updateGroupOwnershipForLeaderboardGroupHierarchyInternal(LeaderboardGroup leaderboardGroup) {
|
||||
updateGroupOwner(leaderboardGroup.getIdentifier());
|
||||
SailingHierarchyWalker.walkFromLeaderboardGroup(service, leaderboardGroup, true,
|
||||
new LeaderboardGroupHierarchyVisitor() {
|
||||
@Override
|
||||
public void visit(Leaderboard leaderboard) {
|
||||
updateGroupOwnershipForLeaderboardHierarchy(leaderboard);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Event event) {
|
||||
// Only events of LeaderboardGroups with overall leaderboard are visited -> no infinite
|
||||
// recursion occurs
|
||||
updateGroupOwnershipForEventHierarchyInternal(event);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void updateGroupOwnershipForLeaderboardHierarchy(Leaderboard leaderboard) {
|
||||
updateGroupOwner(leaderboard.getIdentifier());
|
||||
SailingHierarchyWalker.walkFromLeaderboard(leaderboard, new LeaderboardHierarchyVisitor() {
|
||||
@Override
|
||||
public void visit(TrackedRace race) {
|
||||
updateGroupOwner(race.getIdentifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Boat boat) {
|
||||
if (updateBoats) {
|
||||
updateGroupOwner(boat.getIdentifier());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Competitor competitor) {
|
||||
if (updateCompetitors) {
|
||||
updateGroupOwner(competitor.getIdentifier());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateGroupOwner(QualifiedObjectIdentifier id) {
|
||||
final OwnershipAnnotation ownership = securityService.getOwnership(id);
|
||||
if (updateStrategy.needsUpdate(id, ownership)) {
|
||||
String permissionToCheck = id.getTypeIdentifier() + WildcardPermission.PART_DIVIDER_TOKEN
|
||||
+ DefaultActions.CHANGE_OWNERSHIP.name() + WildcardPermission.PART_DIVIDER_TOKEN
|
||||
+ id.getTypeRelativeObjectIdentifier();
|
||||
SecurityUtils.getSubject().checkPermission(permissionToCheck);
|
||||
objectsToUpdateOwnershipsFor.add(id);
|
||||
}
|
||||
}
|
||||
|
||||
private void commitChanges() {
|
||||
final UserGroup groupOwnerToSet = updateStrategy.getNewGroupOwner();
|
||||
for (QualifiedObjectIdentifier id : objectsToUpdateOwnershipsFor) {
|
||||
final OwnershipAnnotation ownership = securityService.getOwnership(id);
|
||||
securityService.setOwnership(id, ownership == null ? null : (User) ownership.getAnnotation().getUserOwner(),
|
||||
groupOwnerToSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
package com.sap.sailing.server.hierarchy;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sap.sailing.domain.base.Boat;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.Event;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
/**
|
||||
* Util to walk the sailing domain object hierarchy using visitors. This util encapsulates specific hierarchy logic
|
||||
* necessary because the hierarchy is not always obvious and consistent. For event series, the {@link LeaderboardGroup}
|
||||
* is meant to be the top level domain object and defines a hierarchy containing several {@link Event Events} and
|
||||
* {@link Leaderboard Leaderboards}. For other event types, the {@link LeaderboardGroup} is only a related object of the
|
||||
* {@link Event} defining the top level point of a hierarchy.
|
||||
*/
|
||||
public final class SailingHierarchyWalker {
|
||||
|
||||
private SailingHierarchyWalker() {
|
||||
}
|
||||
|
||||
public static void walkFromEvent(final Event event, final boolean includeLeaderboardGroupsWithOverallLeaderboard,
|
||||
final EventHierarchyVisitor visitor) {
|
||||
final Map<Leaderboard, Set<LeaderboardGroup>> leaderboardsToLeaderboardGroups = new HashMap<>();
|
||||
for (LeaderboardGroup lg : event.getLeaderboardGroups()) {
|
||||
if (includeLeaderboardGroupsWithOverallLeaderboard || !lg.hasOverallLeaderboard()) {
|
||||
visitor.visit(lg);
|
||||
}
|
||||
for (Leaderboard lb : lg.getLeaderboards()) {
|
||||
Util.add(leaderboardsToLeaderboardGroups, lb, lg);
|
||||
}
|
||||
}
|
||||
for (Map.Entry<Leaderboard, Set<LeaderboardGroup>> entry : leaderboardsToLeaderboardGroups.entrySet()) {
|
||||
visitor.visit(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public static void walkFromLeaderboardGroup(RacingEventService service, final LeaderboardGroup leaderboardGroup,
|
||||
final boolean includeEventsIfLeaderboardGroupHasOverallLeaderboard,
|
||||
final LeaderboardGroupHierarchyVisitor visitor) {
|
||||
boolean visitEvents = includeEventsIfLeaderboardGroupHasOverallLeaderboard
|
||||
&& leaderboardGroup.hasOverallLeaderboard();
|
||||
|
||||
if (visitEvents) {
|
||||
for (Event event : service.getAllEvents()) {
|
||||
if (Util.contains(event.getLeaderboardGroups(), leaderboardGroup)) {
|
||||
visitor.visit(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Leaderboard lb : leaderboardGroup.getLeaderboards()) {
|
||||
visitor.visit(lb);
|
||||
}
|
||||
}
|
||||
|
||||
public static void walkFromLeaderboard(final Leaderboard leaderboard, final LeaderboardHierarchyVisitor visitor) {
|
||||
for (TrackedRace race : leaderboard.getTrackedRaces()) {
|
||||
visitor.visit(race);
|
||||
}
|
||||
for (Competitor comp : leaderboard.getCompetitors()) {
|
||||
visitor.visit(comp);
|
||||
}
|
||||
for (Boat boat : leaderboard.getAllBoats()) {
|
||||
visitor.visit(boat);
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -1,6 +1,7 @@
|
||||
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;
|
||||
@@ -18,7 +19,8 @@ public class SailingViewerRole extends RolePrototype {
|
||||
super("sailing_viewer", "c42948df-517b-45cb-9fa9-d1e79f18e115",
|
||||
WildcardPermission.builder().withTypes(SecuredDomainType.EVENT, SecuredDomainType.LEADERBOARD_GROUP,
|
||||
SecuredDomainType.LEADERBOARD, SecuredDomainType.REGATTA, SecuredDomainType.TRACKED_RACE)
|
||||
.withActions(DefaultActions.READ).build());
|
||||
.withActions(DefaultActions.READ).build(), WildcardPermission.builder().withTypes(SecuredDomainType.COMPETITOR, SecuredDomainType.BOAT)
|
||||
.withActions(CompetitorAndBoatActions.READ_PUBLIC).build());
|
||||
}
|
||||
|
||||
public static SailingViewerRole getInstance() {
|
||||
|
||||
+1
-1
@@ -505,7 +505,7 @@
|
||||
<!-- GWT version detected from dependencyManagement -->
|
||||
<execution>
|
||||
<configuration>
|
||||
<extraJvmArgs>-Dgwt.persistentunitcache=false -Xmx2560m -Djava.io.tmpdir=${env.TMP}</extraJvmArgs>
|
||||
<extraJvmArgs>-Dgwt.persistentunitcache=false -Xmx2560m -Djava.io.tmpdir=${env.TMP} -Dgwt.watchFileChanges=false</extraJvmArgs>
|
||||
<fragmentCount>4</fragmentCount>
|
||||
<!--
|
||||
<userAgents>chrome</userAgents>
|
||||
|
||||
Reference in new issue
Block a user