mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-09 22:01:02 +00:00
Merge branch 'bug2589' into bug3493
This commit is contained in:
commit
7ce05e81a9
24 files changed
+389
-38
No files matched your search
+66
-3
@@ -1,6 +1,10 @@
|
|||||||
package com.sap.sailing.domain.common.security;
|
package com.sap.sailing.domain.common.security;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public enum Permission implements com.sap.sse.security.shared.Permission {
|
public enum Permission implements com.sap.sse.security.shared.Permission {
|
||||||
|
// AdminConsole permissions
|
||||||
MANAGE_EVENTS,
|
MANAGE_EVENTS,
|
||||||
MANAGE_REGATTAS,
|
MANAGE_REGATTAS,
|
||||||
MANAGE_TRACKED_RACES,
|
MANAGE_TRACKED_RACES,
|
||||||
@@ -23,10 +27,69 @@ public enum Permission implements com.sap.sse.security.shared.Permission {
|
|||||||
MANAGE_USERS,
|
MANAGE_USERS,
|
||||||
MANAGE_FILE_STORAGE,
|
MANAGE_FILE_STORAGE,
|
||||||
MANAGE_MARK_PASSINGS,
|
MANAGE_MARK_PASSINGS,
|
||||||
CAN_REPLAY_DURING_LIVE_RACES;
|
CAN_REPLAY_DURING_LIVE_RACES,
|
||||||
|
|
||||||
|
// back-end permissions
|
||||||
|
EVENT,
|
||||||
|
REGATTA,
|
||||||
|
LEADERBOARD,
|
||||||
|
LEADERBOARD_GROUP,
|
||||||
|
TRACKED_RACE
|
||||||
|
;
|
||||||
|
|
||||||
|
// TODO once we can use Java8 here, move this up into a "default" method on the Permission interface
|
||||||
@Override
|
@Override
|
||||||
public String getStringPermission() {
|
public String getStringPermission(com.sap.sse.security.shared.Permission.Mode... modes) {
|
||||||
return name()+":";
|
final String result;
|
||||||
|
if (modes==null || modes.length==0) {
|
||||||
|
result = name();
|
||||||
|
} else {
|
||||||
|
final StringBuilder modesString = new StringBuilder();
|
||||||
|
boolean first = true;
|
||||||
|
for (com.sap.sse.security.shared.Permission.Mode mode : modes) {
|
||||||
|
if (first) {
|
||||||
|
first = false;
|
||||||
|
} else {
|
||||||
|
modesString.append(',');
|
||||||
|
}
|
||||||
|
modesString.append(mode.getStringPermission());
|
||||||
|
}
|
||||||
|
result = name()+":"+modesString.toString();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO once we can use Java8 here, move this up into a "default" method on the Permission interface
|
||||||
|
@Override
|
||||||
|
public String getStringPermissionForObjects(com.sap.sse.security.shared.Permission.Mode mode, String... objectIdentifiers) {
|
||||||
|
final StringBuilder result = new StringBuilder(getStringPermission(mode));
|
||||||
|
if (objectIdentifiers!=null && objectIdentifiers.length>0) {
|
||||||
|
result.append(':');
|
||||||
|
boolean first = true;
|
||||||
|
for (String objectIdentifier : objectIdentifiers) {
|
||||||
|
if (first) {
|
||||||
|
first = false;
|
||||||
|
} else {
|
||||||
|
result.append(',');
|
||||||
|
}
|
||||||
|
result.append(objectIdentifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mode of interaction with a resource; used as the second element of a wildcard permission
|
||||||
|
*
|
||||||
|
* @author Axel Uhl (d043530)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static enum Mode implements com.sap.sse.security.shared.Permission.Mode {
|
||||||
|
CREATE, READ, UPDATE, DELETE;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStringPermission() {
|
||||||
|
return name();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+30
-4
@@ -13,13 +13,39 @@ public class SailingPermissionsForRoleProvider implements PermissionsForRoleProv
|
|||||||
public Iterable<String> getPermissions(String role) {
|
public Iterable<String> getPermissions(String role) {
|
||||||
final Iterable<String> result;
|
final Iterable<String> result;
|
||||||
if (DefaultRoles.ADMIN.getRolename().equals(role)) {
|
if (DefaultRoles.ADMIN.getRolename().equals(role)) {
|
||||||
return Collections.<String>singletonList("*");
|
result = Collections.<String>singletonList("*");
|
||||||
} else if (Roles.eventmanager.getRolename().equals(role)) {
|
} else if (Roles.eventmanager.getRolename().equals(role)) {
|
||||||
return asList(Permission.MANAGE_MEDIA, Permission.MANAGE_MARK_PASSINGS);
|
result = asList(
|
||||||
|
// RaceBoard:
|
||||||
|
Permission.MANAGE_MEDIA,
|
||||||
|
Permission.MANAGE_MARK_PASSINGS,
|
||||||
|
|
||||||
|
// AdminConsole:
|
||||||
|
Permission.MANAGE_ALL_COMPETITORS,
|
||||||
|
Permission.MANAGE_COURSE_LAYOUT,
|
||||||
|
Permission.MANAGE_DEVICE_CONFIGURATION,
|
||||||
|
Permission.MANAGE_EVENTS,
|
||||||
|
Permission.MANAGE_IGTIMI_ACCOUNTS,
|
||||||
|
Permission.MANAGE_LEADERBOARD_GROUPS,
|
||||||
|
Permission.MANAGE_LEADERBOARDS,
|
||||||
|
Permission.MANAGE_MEDIA,
|
||||||
|
Permission.MANAGE_RACELOG_TRACKING,
|
||||||
|
Permission.MANAGE_REGATTAS,
|
||||||
|
Permission.MANAGE_RESULT_IMPORT_URLS,
|
||||||
|
Permission.MANAGE_STRUCTURE_IMPORT_URLS,
|
||||||
|
Permission.MANAGE_TRACKED_RACES,
|
||||||
|
Permission.MANAGE_WIND,
|
||||||
|
|
||||||
|
// back-end:
|
||||||
|
Permission.EVENT,
|
||||||
|
Permission.REGATTA,
|
||||||
|
Permission.LEADERBOARD,
|
||||||
|
Permission.LEADERBOARD_GROUP
|
||||||
|
);
|
||||||
} else if (Roles.mediaeditor.getRolename().equals(role)) {
|
} else if (Roles.mediaeditor.getRolename().equals(role)) {
|
||||||
return asList(Permission.MANAGE_MEDIA);
|
result = asList(Permission.MANAGE_MEDIA);
|
||||||
} else if (Roles.moderator.getRolename().equals(role)) {
|
} else if (Roles.moderator.getRolename().equals(role)) {
|
||||||
return asList(Permission.CAN_REPLAY_DURING_LIVE_RACES);
|
result = asList(Permission.CAN_REPLAY_DURING_LIVE_RACES);
|
||||||
} else {
|
} else {
|
||||||
result = Collections.emptyList();
|
result = Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ Require-Bundle: org.json.simple;bundle-version="1.1.0",
|
|||||||
com.sap.sailing.domain,
|
com.sap.sailing.domain,
|
||||||
com.sap.sailing.declination,
|
com.sap.sailing.declination,
|
||||||
com.sap.sse.common,
|
com.sap.sse.common,
|
||||||
com.sap.sse
|
com.sap.sse,
|
||||||
|
com.sap.sse.security
|
||||||
Import-Package: javax.ws.rs;version="1.1.1",
|
Import-Package: javax.ws.rs;version="1.1.1",
|
||||||
javax.ws.rs.core;version="1.1.1",
|
javax.ws.rs.core;version="1.1.1",
|
||||||
javax.ws.rs.ext;version="1.1.1",
|
javax.ws.rs.ext;version="1.1.1",
|
||||||
|
|||||||
+3
-1
@@ -6,12 +6,14 @@ import java.util.Set;
|
|||||||
|
|
||||||
import javax.ws.rs.core.Application;
|
import javax.ws.rs.core.Application;
|
||||||
|
|
||||||
|
import com.sap.sse.security.jaxrs.ShiroAuthorizationExceptionTo401ResponseMapper;
|
||||||
|
|
||||||
public class RestApiApplication extends Application {
|
public class RestApiApplication extends Application {
|
||||||
public RestApiApplication() {
|
public RestApiApplication() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Class<?>> getClasses() {
|
public Set<Class<?>> getClasses() {
|
||||||
return new HashSet<Class<?>>(Arrays.asList(new Class<?>[] { AuthorizationCallback.class }));
|
return new HashSet<Class<?>>(Arrays.asList(new Class<?>[] { AuthorizationCallback.class, ShiroAuthorizationExceptionTo401ResponseMapper.class }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Executable → Regular
+65
-2
@@ -52,6 +52,7 @@ import java.util.zip.GZIPInputStream;
|
|||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
|
|
||||||
import org.apache.http.client.ClientProtocolException;
|
import org.apache.http.client.ClientProtocolException;
|
||||||
|
import org.apache.shiro.SecurityUtils;
|
||||||
import org.osgi.framework.BundleContext;
|
import org.osgi.framework.BundleContext;
|
||||||
import org.osgi.framework.InvalidSyntaxException;
|
import org.osgi.framework.InvalidSyntaxException;
|
||||||
import org.osgi.framework.ServiceReference;
|
import org.osgi.framework.ServiceReference;
|
||||||
@@ -216,6 +217,8 @@ import com.sap.sailing.domain.common.racelog.tracking.RaceLogTrackingState;
|
|||||||
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
|
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
|
||||||
import com.sap.sailing.domain.common.tracking.GPSFix;
|
import com.sap.sailing.domain.common.tracking.GPSFix;
|
||||||
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
||||||
|
import com.sap.sailing.domain.common.security.Permission;
|
||||||
|
import com.sap.sailing.domain.common.security.Permission.Mode;
|
||||||
import com.sap.sailing.domain.common.tracking.impl.GPSFixImpl;
|
import com.sap.sailing.domain.common.tracking.impl.GPSFixImpl;
|
||||||
import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl;
|
import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl;
|
||||||
import com.sap.sailing.domain.igtimiadapter.Account;
|
import com.sap.sailing.domain.igtimiadapter.Account;
|
||||||
@@ -2450,12 +2453,14 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StrippedLeaderboardDTO updateLeaderboard(String leaderboardName, String newLeaderboardName, String newLeaderboardDisplayName, int[] newDiscardingThresholds, UUID newCourseAreaId) {
|
public StrippedLeaderboardDTO updateLeaderboard(String leaderboardName, String newLeaderboardName, String newLeaderboardDisplayName, int[] newDiscardingThresholds, UUID newCourseAreaId) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName));
|
||||||
Leaderboard updatedLeaderboard = getService().apply(new UpdateLeaderboard(leaderboardName, newLeaderboardName, newLeaderboardDisplayName, newDiscardingThresholds, newCourseAreaId));
|
Leaderboard updatedLeaderboard = getService().apply(new UpdateLeaderboard(leaderboardName, newLeaderboardName, newLeaderboardDisplayName, newDiscardingThresholds, newCourseAreaId));
|
||||||
return createStrippedLeaderboardDTO(updatedLeaderboard, false, false);
|
return createStrippedLeaderboardDTO(updatedLeaderboard, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeLeaderboards(Collection<String> leaderboardNames) {
|
public void removeLeaderboards(Collection<String> leaderboardNames) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.DELETE, leaderboardNames.toArray(new String[0])));
|
||||||
for (String leaderoardName : leaderboardNames) {
|
for (String leaderoardName : leaderboardNames) {
|
||||||
removeLeaderboard(leaderoardName);
|
removeLeaderboard(leaderoardName);
|
||||||
}
|
}
|
||||||
@@ -2463,21 +2468,25 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeLeaderboard(String leaderboardName) {
|
public void removeLeaderboard(String leaderboardName) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.DELETE, leaderboardName));
|
||||||
getService().apply(new RemoveLeaderboard(leaderboardName));
|
getService().apply(new RemoveLeaderboard(leaderboardName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renameLeaderboard(String leaderboardName, String newLeaderboardName) {
|
public void renameLeaderboard(String leaderboardName, String newLeaderboardName) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName));
|
||||||
getService().apply(new RenameLeaderboard(leaderboardName, newLeaderboardName));
|
getService().apply(new RenameLeaderboard(leaderboardName, newLeaderboardName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addColumnToLeaderboard(String columnName, String leaderboardName, boolean medalRace) {
|
public void addColumnToLeaderboard(String columnName, String leaderboardName, boolean medalRace) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName));
|
||||||
getService().apply(new AddColumnToLeaderboard(columnName, leaderboardName, medalRace));
|
getService().apply(new AddColumnToLeaderboard(columnName, leaderboardName, medalRace));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addColumnsToLeaderboard(String leaderboardName, List<com.sap.sse.common.Util.Pair<String, Boolean>> columnsToAdd) {
|
public void addColumnsToLeaderboard(String leaderboardName, List<com.sap.sse.common.Util.Pair<String, Boolean>> columnsToAdd) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName));
|
||||||
for(com.sap.sse.common.Util.Pair<String, Boolean> columnToAdd: columnsToAdd) {
|
for(com.sap.sse.common.Util.Pair<String, Boolean> columnToAdd: columnsToAdd) {
|
||||||
getService().apply(new AddColumnToLeaderboard(columnToAdd.getA(), leaderboardName, columnToAdd.getB()));
|
getService().apply(new AddColumnToLeaderboard(columnToAdd.getA(), leaderboardName, columnToAdd.getB()));
|
||||||
}
|
}
|
||||||
@@ -2485,6 +2494,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeLeaderboardColumns(String leaderboardName, List<String> columnsToRemove) {
|
public void removeLeaderboardColumns(String leaderboardName, List<String> columnsToRemove) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName));
|
||||||
for (String columnToRemove : columnsToRemove) {
|
for (String columnToRemove : columnsToRemove) {
|
||||||
getService().apply(new RemoveLeaderboardColumn(columnToRemove, leaderboardName));
|
getService().apply(new RemoveLeaderboardColumn(columnToRemove, leaderboardName));
|
||||||
}
|
}
|
||||||
@@ -2492,27 +2502,32 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeLeaderboardColumn(String leaderboardName, String columnName) {
|
public void removeLeaderboardColumn(String leaderboardName, String columnName) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName));
|
||||||
getService().apply(new RemoveLeaderboardColumn(columnName, leaderboardName));
|
getService().apply(new RemoveLeaderboardColumn(columnName, leaderboardName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renameLeaderboardColumn(String leaderboardName, String oldColumnName, String newColumnName) {
|
public void renameLeaderboardColumn(String leaderboardName, String oldColumnName, String newColumnName) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName));
|
||||||
getService().apply(new RenameLeaderboardColumn(leaderboardName, oldColumnName, newColumnName));
|
getService().apply(new RenameLeaderboardColumn(leaderboardName, oldColumnName, newColumnName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateLeaderboardColumnFactor(String leaderboardName, String columnName, Double newFactor) {
|
public void updateLeaderboardColumnFactor(String leaderboardName, String columnName, Double newFactor) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName));
|
||||||
getService().apply(new UpdateLeaderboardColumnFactor(leaderboardName, columnName, newFactor));
|
getService().apply(new UpdateLeaderboardColumnFactor(leaderboardName, columnName, newFactor));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void suppressCompetitorInLeaderboard(String leaderboardName, String competitorIdAsString, boolean suppressed) {
|
public void suppressCompetitorInLeaderboard(String leaderboardName, String competitorIdAsString, boolean suppressed) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName));
|
||||||
getService().apply(new SetSuppressedFlagForCompetitorInLeaderboard(leaderboardName, competitorIdAsString, suppressed));
|
getService().apply(new SetSuppressedFlagForCompetitorInLeaderboard(leaderboardName, competitorIdAsString, suppressed));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean connectTrackedRaceToLeaderboardColumn(String leaderboardName, String raceColumnName,
|
public boolean connectTrackedRaceToLeaderboardColumn(String leaderboardName, String raceColumnName,
|
||||||
String fleetName, RegattaAndRaceIdentifier raceIdentifier) {
|
String fleetName, RegattaAndRaceIdentifier raceIdentifier) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName));
|
||||||
Object principal = SessionUtils.getPrincipal();
|
Object principal = SessionUtils.getPrincipal();
|
||||||
if (principal != null) {
|
if (principal != null) {
|
||||||
logger.info(String.format("%s linked race column %s %s (%s) with tracked race %s.", principal.toString(),
|
logger.info(String.format("%s linked race column %s %s (%s) with tracked race %s.", principal.toString(),
|
||||||
@@ -2526,6 +2541,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, RegattaAndRaceIdentifier> getRegattaAndRaceNameOfTrackedRaceConnectedToLeaderboardColumn(String leaderboardName, String raceColumnName) {
|
public Map<String, RegattaAndRaceIdentifier> getRegattaAndRaceNameOfTrackedRaceConnectedToLeaderboardColumn(String leaderboardName, String raceColumnName) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.READ, leaderboardName));
|
||||||
Map<String, RegattaAndRaceIdentifier> result = new HashMap<String, RegattaAndRaceIdentifier>();
|
Map<String, RegattaAndRaceIdentifier> result = new HashMap<String, RegattaAndRaceIdentifier>();
|
||||||
Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName);
|
Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName);
|
||||||
if (leaderboard != null) {
|
if (leaderboard != null) {
|
||||||
@@ -2546,17 +2562,20 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disconnectLeaderboardColumnFromTrackedRace(String leaderboardName, String raceColumnName, String fleetName) {
|
public void disconnectLeaderboardColumnFromTrackedRace(String leaderboardName, String raceColumnName, String fleetName) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName));
|
||||||
getService().apply(new DisconnectLeaderboardColumnFromTrackedRace(leaderboardName, raceColumnName, fleetName));
|
getService().apply(new DisconnectLeaderboardColumnFromTrackedRace(leaderboardName, raceColumnName, fleetName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateLeaderboardCarryValue(String leaderboardName, String competitorIdAsString, Double carriedPoints) {
|
public void updateLeaderboardCarryValue(String leaderboardName, String competitorIdAsString, Double carriedPoints) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName));
|
||||||
getService().apply(new UpdateLeaderboardCarryValue(leaderboardName, competitorIdAsString, carriedPoints));
|
getService().apply(new UpdateLeaderboardCarryValue(leaderboardName, competitorIdAsString, carriedPoints));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public com.sap.sse.common.Util.Triple<Double, Double, Boolean> updateLeaderboardMaxPointsReason(String leaderboardName, String competitorIdAsString, String raceColumnName,
|
public com.sap.sse.common.Util.Triple<Double, Double, Boolean> updateLeaderboardMaxPointsReason(String leaderboardName, String competitorIdAsString, String raceColumnName,
|
||||||
MaxPointsReason maxPointsReason, Date date) throws NoWindException {
|
MaxPointsReason maxPointsReason, Date date) throws NoWindException {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName));
|
||||||
return getService().apply(
|
return getService().apply(
|
||||||
new UpdateLeaderboardMaxPointsReason(leaderboardName, raceColumnName, competitorIdAsString,
|
new UpdateLeaderboardMaxPointsReason(leaderboardName, raceColumnName, competitorIdAsString,
|
||||||
maxPointsReason, new MillisecondsTimePoint(date)));
|
maxPointsReason, new MillisecondsTimePoint(date)));
|
||||||
@@ -2565,6 +2584,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
|||||||
@Override
|
@Override
|
||||||
public com.sap.sse.common.Util.Triple<Double, Double, Boolean> updateLeaderboardScoreCorrection(String leaderboardName,
|
public com.sap.sse.common.Util.Triple<Double, Double, Boolean> updateLeaderboardScoreCorrection(String leaderboardName,
|
||||||
String competitorIdAsString, String columnName, Double correctedScore, Date date) throws NoWindException {
|
String competitorIdAsString, String columnName, Double correctedScore, Date date) throws NoWindException {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName));
|
||||||
return getService().apply(
|
return getService().apply(
|
||||||
new UpdateLeaderboardScoreCorrection(leaderboardName, columnName, competitorIdAsString, correctedScore,
|
new UpdateLeaderboardScoreCorrection(leaderboardName, columnName, competitorIdAsString, correctedScore,
|
||||||
new MillisecondsTimePoint(date)));
|
new MillisecondsTimePoint(date)));
|
||||||
@@ -2572,6 +2592,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateLeaderboardScoreCorrectionMetadata(String leaderboardName, Date timePointOfLastCorrectionValidity, String comment) {
|
public void updateLeaderboardScoreCorrectionMetadata(String leaderboardName, Date timePointOfLastCorrectionValidity, String comment) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName));
|
||||||
getService().apply(
|
getService().apply(
|
||||||
new UpdateLeaderboardScoreCorrectionMetadata(leaderboardName,
|
new UpdateLeaderboardScoreCorrectionMetadata(leaderboardName,
|
||||||
timePointOfLastCorrectionValidity == null ? null : new MillisecondsTimePoint(timePointOfLastCorrectionValidity),
|
timePointOfLastCorrectionValidity == null ? null : new MillisecondsTimePoint(timePointOfLastCorrectionValidity),
|
||||||
@@ -2580,6 +2601,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateLeaderboardScoreCorrectionsAndMaxPointsReasons(BulkScoreCorrectionDTO updates) throws NoWindException {
|
public void updateLeaderboardScoreCorrectionsAndMaxPointsReasons(BulkScoreCorrectionDTO updates) throws NoWindException {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, updates.getLeaderboardName()));
|
||||||
Date dateForResults = new Date(); // we don't care about the result date/time here; use current date as default
|
Date dateForResults = new Date(); // we don't care about the result date/time here; use current date as default
|
||||||
for (Map.Entry<String, Map<String, Double>> e : updates.getScoreUpdatesForRaceColumnByCompetitorIdAsString().entrySet()) {
|
for (Map.Entry<String, Map<String, Double>> e : updates.getScoreUpdatesForRaceColumnByCompetitorIdAsString().entrySet()) {
|
||||||
for (Map.Entry<String, Double> raceColumnNameAndCorrectedScore : e.getValue().entrySet()) {
|
for (Map.Entry<String, Double> raceColumnNameAndCorrectedScore : e.getValue().entrySet()) {
|
||||||
@@ -2597,21 +2619,25 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateCompetitorDisplayNameInLeaderboard(String leaderboardName, String competitorIdAsString, String displayName) {
|
public void updateCompetitorDisplayNameInLeaderboard(String leaderboardName, String competitorIdAsString, String displayName) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName));
|
||||||
getService().apply(new UpdateCompetitorDisplayNameInLeaderboard(leaderboardName, competitorIdAsString, displayName));
|
getService().apply(new UpdateCompetitorDisplayNameInLeaderboard(leaderboardName, competitorIdAsString, displayName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void moveLeaderboardColumnUp(String leaderboardName, String columnName) {
|
public void moveLeaderboardColumnUp(String leaderboardName, String columnName) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName));
|
||||||
getService().apply(new MoveLeaderboardColumnUp(leaderboardName, columnName));
|
getService().apply(new MoveLeaderboardColumnUp(leaderboardName, columnName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void moveLeaderboardColumnDown(String leaderboardName, String columnName) {
|
public void moveLeaderboardColumnDown(String leaderboardName, String columnName) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName));
|
||||||
getService().apply(new MoveLeaderboardColumnDown(leaderboardName, columnName));
|
getService().apply(new MoveLeaderboardColumnDown(leaderboardName, columnName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateIsMedalRace(String leaderboardName, String columnName, boolean isMedalRace) {
|
public void updateIsMedalRace(String leaderboardName, String columnName, boolean isMedalRace) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName));
|
||||||
getService().apply(new UpdateIsMedalRace(leaderboardName, columnName, isMedalRace));
|
getService().apply(new UpdateIsMedalRace(leaderboardName, columnName, isMedalRace));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3291,6 +3317,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
|||||||
@Override
|
@Override
|
||||||
public void updateLeaderboardGroup(String oldName, String newName, String newDescription, String newDisplayName,
|
public void updateLeaderboardGroup(String oldName, String newName, String newDescription, String newDisplayName,
|
||||||
List<String> leaderboardNames, int[] overallLeaderboardDiscardThresholds, ScoringSchemeType overallLeaderboardScoringSchemeType) {
|
List<String> leaderboardNames, int[] overallLeaderboardDiscardThresholds, ScoringSchemeType overallLeaderboardScoringSchemeType) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD_GROUP.getStringPermissionForObjects(Mode.UPDATE, oldName));
|
||||||
getService().apply(
|
getService().apply(
|
||||||
new UpdateLeaderboardGroup(oldName, newName, newDescription, newDisplayName,
|
new UpdateLeaderboardGroup(oldName, newName, newDescription, newDisplayName,
|
||||||
leaderboardNames, overallLeaderboardDiscardThresholds, overallLeaderboardScoringSchemeType));
|
leaderboardNames, overallLeaderboardDiscardThresholds, overallLeaderboardScoringSchemeType));
|
||||||
@@ -3850,6 +3877,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
|||||||
@Override
|
@Override
|
||||||
public void updateRegatta(RegattaIdentifier regattaName, Date startDate, Date endDate, UUID defaultCourseAreaUuid,
|
public void updateRegatta(RegattaIdentifier regattaName, Date startDate, Date endDate, UUID defaultCourseAreaUuid,
|
||||||
RegattaConfigurationDTO configurationDTO, boolean useStartTimeInference) {
|
RegattaConfigurationDTO configurationDTO, boolean useStartTimeInference) {
|
||||||
|
Regatta regatta = getService().getRegatta(regattaName);
|
||||||
|
if (regatta != null) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName()));
|
||||||
|
}
|
||||||
TimePoint startTimePoint = startDate != null ? new MillisecondsTimePoint(startDate) : null;
|
TimePoint startTimePoint = startDate != null ? new MillisecondsTimePoint(startDate) : null;
|
||||||
TimePoint endTimePoint = endDate != null ? new MillisecondsTimePoint(endDate) : null;
|
TimePoint endTimePoint = endDate != null ? new MillisecondsTimePoint(endDate) : null;
|
||||||
getService().apply(new UpdateSpecificRegatta(regattaName, startTimePoint, endTimePoint,
|
getService().apply(new UpdateSpecificRegatta(regattaName, startTimePoint, endTimePoint,
|
||||||
@@ -3859,6 +3890,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
|||||||
@Override
|
@Override
|
||||||
public List<RaceColumnInSeriesDTO> addRaceColumnsToSeries(RegattaIdentifier regattaIdentifier, String seriesName,
|
public List<RaceColumnInSeriesDTO> addRaceColumnsToSeries(RegattaIdentifier regattaIdentifier, String seriesName,
|
||||||
List<Pair<String, Integer>> columnNamesWithInsertIndex) {
|
List<Pair<String, Integer>> columnNamesWithInsertIndex) {
|
||||||
|
Regatta regatta = getService().getRegatta(regattaIdentifier);
|
||||||
|
if (regatta != null) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName()));
|
||||||
|
}
|
||||||
List<RaceColumnInSeriesDTO> result = new ArrayList<RaceColumnInSeriesDTO>();
|
List<RaceColumnInSeriesDTO> result = new ArrayList<RaceColumnInSeriesDTO>();
|
||||||
for (Pair<String, Integer> columnNameAndInsertIndex : columnNamesWithInsertIndex) {
|
for (Pair<String, Integer> columnNameAndInsertIndex : columnNamesWithInsertIndex) {
|
||||||
RaceColumnInSeries raceColumnInSeries = getService().apply(
|
RaceColumnInSeries raceColumnInSeries = getService().apply(
|
||||||
@@ -3875,6 +3910,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
|||||||
int[] resultDiscardingThresholds, boolean startsWithZeroScore,
|
int[] resultDiscardingThresholds, boolean startsWithZeroScore,
|
||||||
boolean firstColumnIsNonDiscardableCarryForward, boolean hasSplitFleetContiguousScoring,
|
boolean firstColumnIsNonDiscardableCarryForward, boolean hasSplitFleetContiguousScoring,
|
||||||
List<FleetDTO> fleets) {
|
List<FleetDTO> fleets) {
|
||||||
|
Regatta regatta = getService().getRegatta(regattaIdentifier);
|
||||||
|
if (regatta != null) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName()));
|
||||||
|
}
|
||||||
getService().apply(
|
getService().apply(
|
||||||
new UpdateSeries(regattaIdentifier, seriesName, newSeriesName, isMedal, resultDiscardingThresholds,
|
new UpdateSeries(regattaIdentifier, seriesName, newSeriesName, isMedal, resultDiscardingThresholds,
|
||||||
startsWithZeroScore, firstColumnIsNonDiscardableCarryForward, hasSplitFleetContiguousScoring,
|
startsWithZeroScore, firstColumnIsNonDiscardableCarryForward, hasSplitFleetContiguousScoring,
|
||||||
@@ -3883,6 +3922,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RaceColumnInSeriesDTO addRaceColumnToSeries(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) {
|
public RaceColumnInSeriesDTO addRaceColumnToSeries(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) {
|
||||||
|
Regatta regatta = getService().getRegatta(regattaIdentifier);
|
||||||
|
if (regatta != null) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName()));
|
||||||
|
}
|
||||||
RaceColumnInSeriesDTO result = null;
|
RaceColumnInSeriesDTO result = null;
|
||||||
RaceColumnInSeries raceColumnInSeries = getService().apply(new AddColumnToSeries(regattaIdentifier, seriesName, columnName));
|
RaceColumnInSeries raceColumnInSeries = getService().apply(new AddColumnToSeries(regattaIdentifier, seriesName, columnName));
|
||||||
if(raceColumnInSeries != null) {
|
if(raceColumnInSeries != null) {
|
||||||
@@ -3893,6 +3936,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeRaceColumnsFromSeries(RegattaIdentifier regattaIdentifier, String seriesName, List<String> columnNames) {
|
public void removeRaceColumnsFromSeries(RegattaIdentifier regattaIdentifier, String seriesName, List<String> columnNames) {
|
||||||
|
Regatta regatta = getService().getRegatta(regattaIdentifier);
|
||||||
|
if (regatta != null) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName()));
|
||||||
|
}
|
||||||
for(String columnName: columnNames) {
|
for(String columnName: columnNames) {
|
||||||
getService().apply(new RemoveColumnFromSeries(regattaIdentifier, seriesName, columnName));
|
getService().apply(new RemoveColumnFromSeries(regattaIdentifier, seriesName, columnName));
|
||||||
}
|
}
|
||||||
@@ -3900,16 +3947,28 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeRaceColumnFromSeries(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) {
|
public void removeRaceColumnFromSeries(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) {
|
||||||
|
Regatta regatta = getService().getRegatta(regattaIdentifier);
|
||||||
|
if (regatta != null) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName()));
|
||||||
|
}
|
||||||
getService().apply(new RemoveColumnFromSeries(regattaIdentifier, seriesName, columnName));
|
getService().apply(new RemoveColumnFromSeries(regattaIdentifier, seriesName, columnName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void moveRaceColumnInSeriesUp(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) {
|
public void moveRaceColumnInSeriesUp(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) {
|
||||||
|
Regatta regatta = getService().getRegatta(regattaIdentifier);
|
||||||
|
if (regatta != null) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName()));
|
||||||
|
}
|
||||||
getService().apply(new MoveColumnInSeriesUp(regattaIdentifier, seriesName, columnName));
|
getService().apply(new MoveColumnInSeriesUp(regattaIdentifier, seriesName, columnName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void moveRaceColumnInSeriesDown(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) {
|
public void moveRaceColumnInSeriesDown(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) {
|
||||||
|
Regatta regatta = getService().getRegatta(regattaIdentifier);
|
||||||
|
if (regatta != null) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName()));
|
||||||
|
}
|
||||||
getService().apply(new MoveColumnInSeriesDown(regattaIdentifier, seriesName, columnName));
|
getService().apply(new MoveColumnInSeriesDown(regattaIdentifier, seriesName, columnName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3918,6 +3977,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
|||||||
RegattaCreationParametersDTO seriesNamesWithFleetNamesAndFleetOrderingAndMedal,
|
RegattaCreationParametersDTO seriesNamesWithFleetNamesAndFleetOrderingAndMedal,
|
||||||
boolean persistent, ScoringSchemeType scoringSchemeType, UUID defaultCourseAreaId, boolean useStartTimeInference,
|
boolean persistent, ScoringSchemeType scoringSchemeType, UUID defaultCourseAreaId, boolean useStartTimeInference,
|
||||||
RankingMetrics rankingMetricType) {
|
RankingMetrics rankingMetricType) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.CREATE, regattaName));
|
||||||
TimePoint startTimePoint = startDate != null ? new MillisecondsTimePoint(startDate) : null;
|
TimePoint startTimePoint = startDate != null ? new MillisecondsTimePoint(startDate) : null;
|
||||||
TimePoint endTimePoint = endDate != null ? new MillisecondsTimePoint(endDate) : null;
|
TimePoint endTimePoint = endDate != null ? new MillisecondsTimePoint(endDate) : null;
|
||||||
Regatta regatta = getService().apply(
|
Regatta regatta = getService().apply(
|
||||||
@@ -4164,6 +4224,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void createRegattaFromRegattaDTO(RegattaDTO regatta) {
|
private void createRegattaFromRegattaDTO(RegattaDTO regatta) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.CREATE, regatta.getName()));
|
||||||
this.createRegatta(regatta.getName(), regatta.boatClass.getName(), regatta.startDate, regatta.endDate,
|
this.createRegatta(regatta.getName(), regatta.boatClass.getName(), regatta.startDate, regatta.endDate,
|
||||||
new RegattaCreationParametersDTO(getSeriesCreationParameters(regatta)),
|
new RegattaCreationParametersDTO(getSeriesCreationParameters(regatta)),
|
||||||
true, regatta.scoringScheme, regatta.defaultCourseAreaUuid, regatta.useStartTimeInference,
|
true, regatta.scoringScheme, regatta.defaultCourseAreaUuid, regatta.useStartTimeInference,
|
||||||
@@ -4209,7 +4270,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
|||||||
* as specified by <code>regatta</code>. The domain regatta object is assumed to have no races associated
|
* as specified by <code>regatta</code>. The domain regatta object is assumed to have no races associated
|
||||||
* when this method is called.
|
* when this method is called.
|
||||||
*/
|
*/
|
||||||
private void addRaceColumnsToRegattaSeries(RegattaDTO regatta, String eventName) {
|
private void addRaceColumnsToRegattaSeries(RegattaDTO regatta) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.UPDATE, regatta.getName()));
|
||||||
for (SeriesDTO series : regatta.series) {
|
for (SeriesDTO series : regatta.series) {
|
||||||
List<Pair<String, Integer>> raceNamesAndInsertIndex = new ArrayList<>();
|
List<Pair<String, Integer>> raceNamesAndInsertIndex = new ArrayList<>();
|
||||||
int insertIndex = 0;
|
int insertIndex = 0;
|
||||||
@@ -4226,7 +4288,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
|||||||
final List<String> leaderboardNames = new ArrayList<String>();
|
final List<String> leaderboardNames = new ArrayList<String>();
|
||||||
for (RegattaDTO regatta : regattas) {
|
for (RegattaDTO regatta : regattas) {
|
||||||
createRegattaFromRegattaDTO(regatta);
|
createRegattaFromRegattaDTO(regatta);
|
||||||
addRaceColumnsToRegattaSeries(regatta, newEvent.getName());
|
addRaceColumnsToRegattaSeries(regatta);
|
||||||
if (getLeaderboard(regatta.getName()) == null) {
|
if (getLeaderboard(regatta.getName()) == null) {
|
||||||
leaderboardNames.add(regatta.getName());
|
leaderboardNames.add(regatta.getName());
|
||||||
createRegattaLeaderboard(regatta.getRegattaIdentifier(), regatta.boatClass.toString(), new int[0]);
|
createRegattaLeaderboard(regatta.getRegattaIdentifier(), regatta.boatClass.toString(), new int[0]);
|
||||||
@@ -4248,6 +4310,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
|||||||
|
|
||||||
// create Leaderboard Group
|
// create Leaderboard Group
|
||||||
if (getService().getLeaderboardGroupByName(eventName) == null) {
|
if (getService().getLeaderboardGroupByName(eventName) == null) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD_GROUP.getStringPermissionForObjects(Mode.CREATE, eventName));
|
||||||
CreateLeaderboardGroup createLeaderboardGroupOp = new CreateLeaderboardGroup(eventName, description,
|
CreateLeaderboardGroup createLeaderboardGroupOp = new CreateLeaderboardGroup(eventName, description,
|
||||||
eventName, false, leaderboardNames, null, null);
|
eventName, false, leaderboardNames, null, null);
|
||||||
leaderboardGroupDTO = convertToLeaderboardGroupDTO(getService().apply(createLeaderboardGroupOp), false,
|
leaderboardGroupDTO = convertToLeaderboardGroupDTO(getService().apply(createLeaderboardGroupOp), false,
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ Require-Bundle: com.sap.sailing.domain,
|
|||||||
org.apache.shiro.web;bundle-version="1.2.2",
|
org.apache.shiro.web;bundle-version="1.2.2",
|
||||||
org.apache.shiro.ehcache;bundle-version="1.2.3",
|
org.apache.shiro.ehcache;bundle-version="1.2.3",
|
||||||
org.jvnet.mimepull;bundle-version="1.9.4",
|
org.jvnet.mimepull;bundle-version="1.9.4",
|
||||||
|
com.sap.sse.security.common,
|
||||||
com.sap.sailing.polars,
|
com.sap.sailing.polars,
|
||||||
com.sap.sse.datamining;bundle-version="1.0.0",
|
com.sap.sse.datamining;bundle-version="1.0.0",
|
||||||
com.sap.sse.datamining.shared;bundle-version="1.0.0",
|
com.sap.sse.datamining.shared;bundle-version="1.0.0",
|
||||||
|
|||||||
@@ -203,14 +203,18 @@
|
|||||||
<servlet-name>Jersey REST SPI</servlet-name>
|
<servlet-name>Jersey REST SPI</servlet-name>
|
||||||
<servlet-class>com.sap.sailing.server.gateway.jaxrs.RestServletContainer</servlet-class>
|
<servlet-class>com.sap.sailing.server.gateway.jaxrs.RestServletContainer</servlet-class>
|
||||||
<init-param>
|
<init-param>
|
||||||
<param-name>javax.ws.rs.Application</param-name>
|
<param-name>javax.ws.rs.Application</param-name>
|
||||||
<param-value>com.sap.sailing.server.gateway.jaxrs.spi.RestSpiApplication</param-value>
|
<param-value>com.sap.sailing.server.gateway.jaxrs.spi.RestSpiApplication</param-value>
|
||||||
</init-param>
|
</init-param>
|
||||||
<init-param>
|
<init-param>
|
||||||
<param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
|
<param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
|
||||||
<param-value>com.sap.sailing.server.gateway.jaxrs.AccessControlAndEncodingResponseFilter</param-value>
|
<param-value>com.sap.sailing.server.gateway.jaxrs.AccessControlAndEncodingResponseFilter</param-value>
|
||||||
</init-param>
|
</init-param>
|
||||||
<load-on-startup>1</load-on-startup>
|
<init-param>
|
||||||
|
<param-name>com.sun.jersey.config.property.packages</param-name>
|
||||||
|
<param-value>com.sap.sailing.server.gateway.jaxrs</param-value>
|
||||||
|
</init-param>
|
||||||
|
<load-on-startup>1</load-on-startup>
|
||||||
</servlet>
|
</servlet>
|
||||||
<servlet-mapping>
|
<servlet-mapping>
|
||||||
<servlet-name>Jersey REST SPI</servlet-name>
|
<servlet-name>Jersey REST SPI</servlet-name>
|
||||||
|
|||||||
+3
@@ -13,6 +13,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringEscapeUtils;
|
import org.apache.commons.lang.StringEscapeUtils;
|
||||||
|
import org.apache.shiro.SecurityUtils;
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
import org.json.simple.JSONValue;
|
import org.json.simple.JSONValue;
|
||||||
import org.json.simple.parser.ParseException;
|
import org.json.simple.parser.ParseException;
|
||||||
@@ -22,6 +23,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
|
|||||||
import com.sap.sailing.domain.base.Fleet;
|
import com.sap.sailing.domain.base.Fleet;
|
||||||
import com.sap.sailing.domain.base.RaceColumn;
|
import com.sap.sailing.domain.base.RaceColumn;
|
||||||
import com.sap.sailing.domain.common.racelog.RaceLogServletConstants;
|
import com.sap.sailing.domain.common.racelog.RaceLogServletConstants;
|
||||||
|
import com.sap.sailing.domain.common.security.Permission;
|
||||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||||
import com.sap.sailing.server.RacingEventService;
|
import com.sap.sailing.server.RacingEventService;
|
||||||
import com.sap.sailing.server.gateway.AbstractJsonHttpServlet;
|
import com.sap.sailing.server.gateway.AbstractJsonHttpServlet;
|
||||||
@@ -69,6 +71,7 @@ public class AddEntryToRaceLogJsonPostServlet extends AbstractJsonHttpServlet {
|
|||||||
String.format("Missing parameter '%s'.", RaceLogServletConstants.PARAMS_LEADERBOARD_NAME));
|
String.format("Missing parameter '%s'.", RaceLogServletConstants.PARAMS_LEADERBOARD_NAME));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Permission.Mode.UPDATE, leaderboardName));
|
||||||
|
|
||||||
String raceColumnName = request.getParameter(RaceLogServletConstants.PARAMS_RACE_COLUMN_NAME);
|
String raceColumnName = request.getParameter(RaceLogServletConstants.PARAMS_RACE_COLUMN_NAME);
|
||||||
if (raceColumnName == null) {
|
if (raceColumnName == null) {
|
||||||
|
|||||||
+1
-4
@@ -39,13 +39,11 @@ public class RestServletContainer extends ServletContainer {
|
|||||||
@Override
|
@Override
|
||||||
public void init(ServletConfig config) throws ServletException {
|
public void init(ServletConfig config) throws ServletException {
|
||||||
super.init(config);
|
super.init(config);
|
||||||
|
|
||||||
BundleContext context = (BundleContext) config.getServletContext().getAttribute(OSGI_RFC66_WEBBUNDLE_BUNDLECONTEXT_NAME);
|
BundleContext context = (BundleContext) config.getServletContext().getAttribute(OSGI_RFC66_WEBBUNDLE_BUNDLECONTEXT_NAME);
|
||||||
racingEventServiceTracker = new ServiceTracker<RacingEventService, RacingEventService>(context, RacingEventService.class.getName(), null);
|
racingEventServiceTracker = new ServiceTracker<RacingEventService, RacingEventService>(context, RacingEventService.class.getName(), null);
|
||||||
racingEventServiceTracker.open();
|
racingEventServiceTracker.open();
|
||||||
dataMiningServerTracker = new ServiceTracker<DataMiningServer, DataMiningServer>(context, DataMiningServer.class, null);
|
dataMiningServerTracker = new ServiceTracker<DataMiningServer, DataMiningServer>(context, DataMiningServer.class, null);
|
||||||
dataMiningServerTracker.open();
|
dataMiningServerTracker.open();
|
||||||
|
|
||||||
config.getServletContext().setAttribute(RACING_EVENT_SERVICE_TRACKER_NAME, racingEventServiceTracker);
|
config.getServletContext().setAttribute(RACING_EVENT_SERVICE_TRACKER_NAME, racingEventServiceTracker);
|
||||||
config.getServletContext().setAttribute(DATA_MINING_SERVER_TRACKER_NAME, dataMiningServerTracker);
|
config.getServletContext().setAttribute(DATA_MINING_SERVER_TRACKER_NAME, dataMiningServerTracker);
|
||||||
}
|
}
|
||||||
@@ -53,8 +51,7 @@ public class RestServletContainer extends ServletContainer {
|
|||||||
@Override
|
@Override
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
super.destroy();
|
super.destroy();
|
||||||
|
if (racingEventServiceTracker != null) {
|
||||||
if(racingEventServiceTracker != null) {
|
|
||||||
racingEventServiceTracker.close();
|
racingEventServiceTracker.close();
|
||||||
}
|
}
|
||||||
if (dataMiningServerTracker != null) {
|
if (dataMiningServerTracker != null) {
|
||||||
|
|||||||
+5
@@ -12,11 +12,13 @@ import javax.ws.rs.core.Response;
|
|||||||
import javax.ws.rs.core.Response.Status;
|
import javax.ws.rs.core.Response.Status;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringEscapeUtils;
|
import org.apache.commons.lang.StringEscapeUtils;
|
||||||
|
import org.apache.shiro.SecurityUtils;
|
||||||
import org.json.simple.JSONArray;
|
import org.json.simple.JSONArray;
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
import com.sap.sailing.domain.base.Event;
|
import com.sap.sailing.domain.base.Event;
|
||||||
import com.sap.sailing.domain.base.EventBase;
|
import com.sap.sailing.domain.base.EventBase;
|
||||||
|
import com.sap.sailing.domain.common.security.Permission;
|
||||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||||
import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource;
|
import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource;
|
||||||
import com.sap.sailing.server.gateway.serialization.JsonSerializer;
|
import com.sap.sailing.server.gateway.serialization.JsonSerializer;
|
||||||
@@ -36,6 +38,7 @@ public class EventsResource extends AbstractSailingServerResource {
|
|||||||
@GET
|
@GET
|
||||||
@Produces("application/json;charset=UTF-8")
|
@Produces("application/json;charset=UTF-8")
|
||||||
public Response getEvents() {
|
public Response getEvents() {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.EVENT.getStringPermission(Permission.Mode.READ));
|
||||||
JsonSerializer<EventBase> eventSerializer = new EventBaseJsonSerializer(new VenueJsonSerializer(new CourseAreaJsonSerializer()), new LeaderboardGroupBaseJsonSerializer());
|
JsonSerializer<EventBase> eventSerializer = new EventBaseJsonSerializer(new VenueJsonSerializer(new CourseAreaJsonSerializer()), new LeaderboardGroupBaseJsonSerializer());
|
||||||
JSONArray result = new JSONArray();
|
JSONArray result = new JSONArray();
|
||||||
for (EventBase event : getService().getAllEvents()) {
|
for (EventBase event : getService().getAllEvents()) {
|
||||||
@@ -51,6 +54,7 @@ public class EventsResource extends AbstractSailingServerResource {
|
|||||||
@Produces("application/json;charset=UTF-8")
|
@Produces("application/json;charset=UTF-8")
|
||||||
@Path("{eventId}")
|
@Path("{eventId}")
|
||||||
public Response getEvent(@PathParam("eventId") String eventId) {
|
public Response getEvent(@PathParam("eventId") String eventId) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.EVENT.getStringPermissionForObjects(Permission.Mode.READ, eventId));
|
||||||
Response response;
|
Response response;
|
||||||
UUID eventUuid;
|
UUID eventUuid;
|
||||||
try {
|
try {
|
||||||
@@ -77,6 +81,7 @@ public class EventsResource extends AbstractSailingServerResource {
|
|||||||
@Path("{eventId}/racestates")
|
@Path("{eventId}/racestates")
|
||||||
public Response getRaceStates(@PathParam("eventId") String eventId, @QueryParam("filterByLeaderboard") String filterByLeaderboard,
|
public Response getRaceStates(@PathParam("eventId") String eventId, @QueryParam("filterByLeaderboard") String filterByLeaderboard,
|
||||||
@QueryParam("filterByCourseArea") String filterByCourseArea, @QueryParam("filterByDayOffset") String filterByDayOffset) {
|
@QueryParam("filterByCourseArea") String filterByCourseArea, @QueryParam("filterByDayOffset") String filterByDayOffset) {
|
||||||
|
SecurityUtils.getSubject().checkPermission(Permission.EVENT.getStringPermissionForObjects(Permission.Mode.READ, eventId));
|
||||||
Response response;
|
Response response;
|
||||||
UUID eventUuid;
|
UUID eventUuid;
|
||||||
try {
|
try {
|
||||||
|
|||||||
+6
@@ -5,10 +5,13 @@ import java.util.Set;
|
|||||||
|
|
||||||
import javax.ws.rs.core.Application;
|
import javax.ws.rs.core.Application;
|
||||||
|
|
||||||
|
import com.sap.sse.security.jaxrs.ShiroAuthorizationExceptionTo401ResponseMapper;
|
||||||
|
|
||||||
|
|
||||||
public class RestApiApplication extends Application {
|
public class RestApiApplication extends Application {
|
||||||
public Set<Class<?>> getClasses() {
|
public Set<Class<?>> getClasses() {
|
||||||
HashSet<Class<?>> classes = new HashSet<>();
|
HashSet<Class<?>> classes = new HashSet<>();
|
||||||
|
// RESTlets
|
||||||
classes.add(LeaderboardGroupsResource.class);
|
classes.add(LeaderboardGroupsResource.class);
|
||||||
classes.add(EventsResource.class);
|
classes.add(EventsResource.class);
|
||||||
classes.add(RegattasResource.class);
|
classes.add(RegattasResource.class);
|
||||||
@@ -19,6 +22,9 @@ public class RestApiApplication extends Application {
|
|||||||
classes.add(CompetitorsResource.class);
|
classes.add(CompetitorsResource.class);
|
||||||
classes.add(FileStorageResource.class);
|
classes.add(FileStorageResource.class);
|
||||||
classes.add(DataMiningResource.class);
|
classes.add(DataMiningResource.class);
|
||||||
|
|
||||||
|
// Exception Mapper
|
||||||
|
classes.add(ShiroAuthorizationExceptionTo401ResponseMapper.class);
|
||||||
return classes;
|
return classes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+5
@@ -5,11 +5,16 @@ import java.util.Set;
|
|||||||
|
|
||||||
import javax.ws.rs.core.Application;
|
import javax.ws.rs.core.Application;
|
||||||
|
|
||||||
|
import com.sap.sse.security.jaxrs.ShiroAuthorizationExceptionTo401ResponseMapper;
|
||||||
|
|
||||||
|
|
||||||
public class RestSpiApplication extends Application {
|
public class RestSpiApplication extends Application {
|
||||||
public Set<Class<?>> getClasses() {
|
public Set<Class<?>> getClasses() {
|
||||||
HashSet<Class<?>> classes = new HashSet<>();
|
HashSet<Class<?>> classes = new HashSet<>();
|
||||||
classes.add(MasterDataResource.class);
|
classes.add(MasterDataResource.class);
|
||||||
|
|
||||||
|
// exception mapper
|
||||||
|
classes.add(ShiroAuthorizationExceptionTo401ResponseMapper.class);
|
||||||
return classes;
|
return classes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+37
-2
@@ -7,8 +7,43 @@ public enum DefaultPermissions implements Permission {
|
|||||||
this.stringPermission = stringPermission;
|
this.stringPermission = stringPermission;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStringPermission() {
|
// TODO once we can use Java8 here, move this up into a "default" method on the Permission interface
|
||||||
return stringPermission;
|
public String getStringPermission(Mode... modes) {
|
||||||
|
final String result;
|
||||||
|
if (modes==null || modes.length==0) {
|
||||||
|
result = stringPermission;
|
||||||
|
} else {
|
||||||
|
final StringBuilder modesString = new StringBuilder();
|
||||||
|
boolean first = true;
|
||||||
|
for (Mode mode : modes) {
|
||||||
|
if (first) {
|
||||||
|
first = false;
|
||||||
|
} else {
|
||||||
|
modesString.append(',');
|
||||||
|
}
|
||||||
|
modesString.append(mode.getStringPermission());
|
||||||
|
}
|
||||||
|
result = stringPermission+":"+modesString.toString();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO once we can use Java8 here, move this up into a "default" method on the Permission interface
|
||||||
|
public String getStringPermissionForObjects(Mode mode, String... objectIdentifiers) {
|
||||||
|
final StringBuilder result = new StringBuilder(getStringPermission(mode));
|
||||||
|
if (objectIdentifiers!=null && objectIdentifiers.length>0) {
|
||||||
|
result.append(':');
|
||||||
|
boolean first = true;
|
||||||
|
for (String objectIdentifier : objectIdentifiers) {
|
||||||
|
if (first) {
|
||||||
|
first = false;
|
||||||
|
} else {
|
||||||
|
result.append(',');
|
||||||
|
}
|
||||||
|
result.append(objectIdentifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final String stringPermission;
|
private final String stringPermission;
|
||||||
|
|||||||
@@ -5,5 +5,25 @@ public interface Permission {
|
|||||||
|
|
||||||
int ordinal();
|
int ordinal();
|
||||||
|
|
||||||
String getStringPermission();
|
/**
|
||||||
|
* If one or more modes are specified, a string permission is rendered that has the
|
||||||
|
* {@link Mode#getStringPermission() permission strings} of those modes listed in the second wildcard permission
|
||||||
|
* component. Otherwise, only the primary permission with one segment is returned.
|
||||||
|
*/
|
||||||
|
String getStringPermission(Mode... modes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Produces a string permission for this permission, the <code>mode</code> specified as the second wildcard permission
|
||||||
|
* segment, and the <code>objectIdentifier</code> as the third wildcard permission segment.
|
||||||
|
*/
|
||||||
|
String getStringPermissionForObjects(Mode mode, String... objectIdentifiers);
|
||||||
|
|
||||||
|
public static interface Mode {
|
||||||
|
String name();
|
||||||
|
|
||||||
|
int ordinal();
|
||||||
|
|
||||||
|
String getStringPermission();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+42
-5
@@ -9,10 +9,13 @@ import java.util.Set;
|
|||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import org.apache.shiro.SecurityUtils;
|
||||||
|
|
||||||
import com.sap.sse.security.SocialSettingsKeys;
|
import com.sap.sse.security.SocialSettingsKeys;
|
||||||
import com.sap.sse.security.User;
|
import com.sap.sse.security.User;
|
||||||
import com.sap.sse.security.UserStore;
|
import com.sap.sse.security.UserStore;
|
||||||
import com.sap.sse.security.shared.Account;
|
import com.sap.sse.security.shared.Account;
|
||||||
|
import com.sap.sse.security.shared.DefaultRoles;
|
||||||
import com.sap.sse.security.shared.UserManagementException;
|
import com.sap.sse.security.shared.UserManagementException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -79,6 +82,19 @@ public class UserStoreImpl implements UserStore {
|
|||||||
users.put(u.getName(), u);
|
users.put(u.getName(), u);
|
||||||
addToUsersByEmail(u);
|
addToUsersByEmail(u);
|
||||||
}
|
}
|
||||||
|
for (Entry<String, Map<String, String>> e : preferences.entrySet()) {
|
||||||
|
if (e.getValue() != null) {
|
||||||
|
final String accessToken = e.getValue().get(ACCESS_TOKEN_KEY);
|
||||||
|
if (accessToken != null) {
|
||||||
|
final User user = users.get(e.getKey());
|
||||||
|
if (user != null) {
|
||||||
|
usersByAccessToken.put(accessToken, user);
|
||||||
|
} else {
|
||||||
|
logger.warning("Couldn't find user \""+e.getKey()+"\" for which an access token was found in the preferences");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -128,11 +144,32 @@ public class UserStoreImpl implements UserStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeAccessToken(String username, String accessToken) {
|
public String getAccessToken(String username) {
|
||||||
User user = usersByAccessToken.remove(accessToken);
|
// only the user or an administrator may request a user's access token
|
||||||
if (user != null) {
|
if (SecurityUtils.getSubject().hasRole(DefaultRoles.ADMIN.getRolename()) ||
|
||||||
// the access token actually existed; now we need to update the preferences
|
SecurityUtils.getSubject().getPrincipal().toString().equals(username)) {
|
||||||
unsetPreference(username, ACCESS_TOKEN_KEY);
|
return getPreference(username, ACCESS_TOKEN_KEY);
|
||||||
|
} else {
|
||||||
|
throw new org.apache.shiro.authz.AuthorizationException("Only admin role or owner can retrieve access token");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAccessToken(String username) {
|
||||||
|
// only the user or an administrator may request a user's access token
|
||||||
|
if (SecurityUtils.getSubject().hasRole(DefaultRoles.ADMIN.getRolename()) ||
|
||||||
|
SecurityUtils.getSubject().getPrincipal().toString().equals(username)) {
|
||||||
|
User user = users.get(username);
|
||||||
|
if (user != null) {
|
||||||
|
final String accessToken = getPreference(username, ACCESS_TOKEN_KEY);
|
||||||
|
if (accessToken != null) {
|
||||||
|
usersByAccessToken.remove(accessToken);
|
||||||
|
}
|
||||||
|
// the access token actually existed; now we need to update the preferences
|
||||||
|
unsetPreference(username, ACCESS_TOKEN_KEY);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new org.apache.shiro.authz.AuthorizationException("Only admin role or owner can retrieve access token");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,4 +35,5 @@ Require-Bundle: javax.servlet;bundle-version="2.5.0",
|
|||||||
com.sap.sse,
|
com.sap.sse,
|
||||||
com.sap.sse.mail
|
com.sap.sse.mail
|
||||||
Web-ContextPath: /security
|
Web-ContextPath: /security
|
||||||
Export-Package: com.sap.sse.security
|
Export-Package: com.sap.sse.security,
|
||||||
|
com.sap.sse.security.jaxrs
|
||||||
@@ -67,4 +67,5 @@ bearerToken = com.sap.sse.security.BearerTokenOrBasicOrFormAuthenticationFilter
|
|||||||
/api/restsecurity/login = authc
|
/api/restsecurity/login = authc
|
||||||
/api/restsecurity/logout = logout
|
/api/restsecurity/logout = logout
|
||||||
/api/restsecurity/access_token = bearerToken
|
/api/restsecurity/access_token = bearerToken
|
||||||
|
/api/restsecurity/remove_access_token = bearerToken
|
||||||
/api/restsecurity/hello = bearerToken
|
/api/restsecurity/hello = bearerToken
|
||||||
@@ -159,6 +159,13 @@ public interface SecurityService extends ReplicableWithObjectInputStream<Replica
|
|||||||
*/
|
*/
|
||||||
String createAccessToken(String username);
|
String createAccessToken(String username);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* May be invoked by users with role {@link DefaultRoles#ADMIN} or the user identified by {@code username}. Returns
|
||||||
|
* the last access token previously created by {@link #createAccessToken(String)} or {@code null} if no such access
|
||||||
|
* token was created before for user {@code username} or was {@link #removeAccessToken(String)}.
|
||||||
|
*/
|
||||||
|
String getAccessToken(String username);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Looks up a user by an access token that was created before using {@link #createAccessToken(String)} for same user name.
|
* Looks up a user by an access token that was created before using {@link #createAccessToken(String)} for same user name.
|
||||||
*
|
*
|
||||||
@@ -166,7 +173,7 @@ public interface SecurityService extends ReplicableWithObjectInputStream<Replica
|
|||||||
*/
|
*/
|
||||||
User getUserByAccessToken(String accessToken);
|
User getUserByAccessToken(String accessToken);
|
||||||
|
|
||||||
void removeAccessToken(String username, String accessToken);
|
void removeAccessToken(String username);
|
||||||
|
|
||||||
User loginByAccessToken(String accessToken);
|
User loginByAccessToken(String accessToken);
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import java.util.UUID;
|
|||||||
|
|
||||||
import com.sap.sse.common.Named;
|
import com.sap.sse.common.Named;
|
||||||
import com.sap.sse.security.shared.Account;
|
import com.sap.sse.security.shared.Account;
|
||||||
|
import com.sap.sse.security.shared.DefaultRoles;
|
||||||
import com.sap.sse.security.shared.UserManagementException;
|
import com.sap.sse.security.shared.UserManagementException;
|
||||||
|
|
||||||
public interface UserStore extends Named {
|
public interface UserStore extends Named {
|
||||||
@@ -97,6 +98,12 @@ public interface UserStore extends Named {
|
|||||||
*/
|
*/
|
||||||
boolean setAccessToken(String username, String accessToken);
|
boolean setAccessToken(String username, String accessToken);
|
||||||
|
|
||||||
void removeAccessToken(String username, String accessToken);
|
void removeAccessToken(String username);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The owner and any subject having the {@link DefaultRoles#ADMIN} role can retrieve an existing
|
||||||
|
* authentication token for the user. {@code null} may result in case for the user identified by
|
||||||
|
* {@code username} no access token has previously been {@link #setAccessToken(String, String) set}.
|
||||||
|
*/
|
||||||
|
String getAccessToken(String username);
|
||||||
}
|
}
|
||||||
+1
-1
@@ -22,7 +22,7 @@ public interface ReplicableSecurityService extends SecurityService {
|
|||||||
|
|
||||||
Void internalSetAccessToken(String username, String accessToken);
|
Void internalSetAccessToken(String username, String accessToken);
|
||||||
|
|
||||||
Void internalRemoveAccessToken(String username, String accessToken);
|
Void internalRemoveAccessToken(String username);
|
||||||
|
|
||||||
Boolean internalSetSetting(String key, Object setting);
|
Boolean internalSetSetting(String key, Object setting);
|
||||||
|
|
||||||
|
|||||||
@@ -921,10 +921,15 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
|
|||||||
store.setAccessToken(username, accessToken);
|
store.setAccessToken(username, accessToken);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAccessToken(String username) {
|
||||||
|
return store.getAccessToken(username);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void internalRemoveAccessToken(String username, String accessToken) {
|
public Void internalRemoveAccessToken(String username) {
|
||||||
store.removeAccessToken(username, accessToken);
|
store.removeAccessToken(username);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -934,7 +939,7 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
|
|||||||
if (subject.hasRole(DefaultRoles.ADMIN.name()) || username.equals(subject.getPrincipal().toString())) {
|
if (subject.hasRole(DefaultRoles.ADMIN.name()) || username.equals(subject.getPrincipal().toString())) {
|
||||||
return store.getPreference(username, key);
|
return store.getPreference(username, key);
|
||||||
} else {
|
} else {
|
||||||
throw new SecurityException("User " + subject.getPrincipal().toString()
|
throw new org.apache.shiro.authz.AuthorizationException("User " + subject.getPrincipal().toString()
|
||||||
+ " does not have permission to read preferences of user " + username);
|
+ " does not have permission to read preferences of user " + username);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -955,8 +960,14 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeAccessToken(String username, String accessToken) {
|
public void removeAccessToken(String username) {
|
||||||
apply(s -> s.internalRemoveAccessToken(username, accessToken));
|
Subject subject = SecurityUtils.getSubject();
|
||||||
|
if (subject.hasRole(DefaultRoles.ADMIN.getRolename()) || username.equals(subject.getPrincipal().toString())) {
|
||||||
|
apply(s -> s.internalRemoveAccessToken(username));
|
||||||
|
} else {
|
||||||
|
throw new org.apache.shiro.authz.AuthorizationException("User " + subject.getPrincipal().toString()
|
||||||
|
+ " does not have permission to remove access token of user " + username);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------- Replication -------------
|
// ----------------- Replication -------------
|
||||||
|
|||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
package com.sap.sse.security.jaxrs;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import javax.ws.rs.core.Response.Status;
|
||||||
|
import javax.ws.rs.ext.ExceptionMapper;
|
||||||
|
import javax.ws.rs.ext.Provider;
|
||||||
|
|
||||||
|
import org.apache.shiro.authz.AuthorizationException;
|
||||||
|
|
||||||
|
@Provider
|
||||||
|
public class ShiroAuthorizationExceptionTo401ResponseMapper implements ExceptionMapper<AuthorizationException> {
|
||||||
|
@Override
|
||||||
|
public Response toResponse(AuthorizationException exception) {
|
||||||
|
return Response.status(Status.UNAUTHORIZED).entity(exception.getMessage()).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,10 +5,15 @@ import java.util.Set;
|
|||||||
|
|
||||||
import javax.ws.rs.core.Application;
|
import javax.ws.rs.core.Application;
|
||||||
|
|
||||||
|
import com.sap.sse.security.jaxrs.ShiroAuthorizationExceptionTo401ResponseMapper;
|
||||||
|
|
||||||
public class RestApiApplication extends Application {
|
public class RestApiApplication extends Application {
|
||||||
public Set<Class<?>> getClasses() {
|
public Set<Class<?>> getClasses() {
|
||||||
HashSet<Class<?>> classes = new HashSet<>();
|
HashSet<Class<?>> classes = new HashSet<>();
|
||||||
classes.add(SecurityResource.class);
|
classes.add(SecurityResource.class);
|
||||||
|
|
||||||
|
// exception mapper
|
||||||
|
classes.add(ShiroAuthorizationExceptionTo401ResponseMapper.class);
|
||||||
return classes;
|
return classes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,6 +12,7 @@ import org.apache.shiro.subject.Subject;
|
|||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
import com.sap.sse.security.jaxrs.AbstractSecurityResource;
|
import com.sap.sse.security.jaxrs.AbstractSecurityResource;
|
||||||
|
import com.sun.jersey.api.client.ClientResponse.Status;
|
||||||
|
|
||||||
@Path("/restsecurity")
|
@Path("/restsecurity")
|
||||||
public class SecurityResource extends AbstractSecurityResource {
|
public class SecurityResource extends AbstractSecurityResource {
|
||||||
@@ -62,15 +63,49 @@ public class SecurityResource extends AbstractSecurityResource {
|
|||||||
return respondWithAccessTokenForAuthenticatedSubject();
|
return respondWithAccessTokenForAuthenticatedSubject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/remove_access_token")
|
||||||
|
@Produces("application/json;charset=UTF-8")
|
||||||
|
public Response removeAccessToken() {
|
||||||
|
return removeAccessTokenPost();
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/remove_access_token")
|
||||||
|
@Produces("application/json;charset=UTF-8")
|
||||||
|
public Response removeAccessTokenPost() {
|
||||||
|
final Response result;
|
||||||
|
final Object principal = SecurityUtils.getSubject().getPrincipal();
|
||||||
|
if (principal != null) {
|
||||||
|
final String username = principal.toString();
|
||||||
|
getService().removeAccessToken(username);
|
||||||
|
result = Response.ok().build();
|
||||||
|
} else {
|
||||||
|
result = Response.status(Status.UNAUTHORIZED).build();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private Response respondWithAccessTokenForAuthenticatedSubject() {
|
private Response respondWithAccessTokenForAuthenticatedSubject() {
|
||||||
final String username = SecurityUtils.getSubject().getPrincipal().toString();
|
final Response result;
|
||||||
return respondWithAccessTokenForUser(username);
|
final Object principal = SecurityUtils.getSubject().getPrincipal();
|
||||||
|
if (principal != null) {
|
||||||
|
final String username = principal.toString();
|
||||||
|
result = respondWithAccessTokenForUser(username);
|
||||||
|
} else {
|
||||||
|
result = Response.status(Status.UNAUTHORIZED).build();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Response respondWithAccessTokenForUser(final String username) {
|
Response respondWithAccessTokenForUser(final String username) {
|
||||||
JSONObject response = new JSONObject();
|
JSONObject response = new JSONObject();
|
||||||
response.put("username", username);
|
response.put("username", username);
|
||||||
response.put("access_token", getService().createAccessToken(username));
|
String accessToken = getService().getAccessToken(username);
|
||||||
|
if (accessToken == null) {
|
||||||
|
accessToken = getService().createAccessToken(username);
|
||||||
|
}
|
||||||
|
response.put("access_token", accessToken);
|
||||||
return Response.ok(response.toJSONString(), MediaType.APPLICATION_JSON_TYPE).build();
|
return Response.ok(response.toJSONString(), MediaType.APPLICATION_JSON_TYPE).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user