mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-20 12:45:35 +00:00
introduced Jersey ExceptionMapper for Shiro's AuthorizationException
This commit is contained in:
+59
-3
@@ -1,6 +1,9 @@
|
||||
package com.sap.sailing.domain.common.security;
|
||||
|
||||
|
||||
|
||||
public enum Permission implements com.sap.sse.security.shared.Permission {
|
||||
// AdminConsole permissions
|
||||
MANAGE_EVENTS,
|
||||
MANAGE_REGATTAS,
|
||||
MANAGE_TRACKED_RACES,
|
||||
@@ -20,10 +23,63 @@ public enum Permission implements com.sap.sse.security.shared.Permission {
|
||||
MANAGE_MASTERDATA_IMPORT,
|
||||
MANAGE_DEVICE_CONFIGURATION,
|
||||
MANAGE_USERS,
|
||||
MANAGE_FILE_STORAGE;
|
||||
MANAGE_FILE_STORAGE,
|
||||
|
||||
// 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
|
||||
public String getStringPermission() {
|
||||
return name()+":";
|
||||
public String getStringPermission(com.sap.sse.security.shared.Permission.Mode... modes) {
|
||||
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) {
|
||||
for (String objectIdentifier : objectIdentifiers) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+26
-1
@@ -1,5 +1,6 @@
|
||||
package com.sap.sailing.domain.common.security;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import com.sap.sse.security.shared.DefaultRoles;
|
||||
@@ -12,7 +13,31 @@ public class SailingPermissionsForRoleProvider implements PermissionsForRoleProv
|
||||
public Iterable<String> getPermissions(String role) {
|
||||
final Iterable<String> result;
|
||||
if (DefaultRoles.ADMIN.getRolename().equals(role)) {
|
||||
return Collections.<String>singletonList("*");
|
||||
result = Collections.<String>singletonList("*");
|
||||
} else if (Roles.eventmanager.getRolename().equals(role)) {
|
||||
result = Arrays.asList(
|
||||
// AdminConsole:
|
||||
Permission.MANAGE_ALL_COMPETITORS.getStringPermission(),
|
||||
Permission.MANAGE_COURSE_LAYOUT.getStringPermission(),
|
||||
Permission.MANAGE_DEVICE_CONFIGURATION.getStringPermission(),
|
||||
Permission.MANAGE_EVENTS.getStringPermission(),
|
||||
Permission.MANAGE_IGTIMI_ACCOUNTS.getStringPermission(),
|
||||
Permission.MANAGE_LEADERBOARD_GROUPS.getStringPermission(),
|
||||
Permission.MANAGE_LEADERBOARDS.getStringPermission(),
|
||||
Permission.MANAGE_MEDIA.getStringPermission(),
|
||||
Permission.MANAGE_RACELOG_TRACKING.getStringPermission(),
|
||||
Permission.MANAGE_REGATTAS.getStringPermission(),
|
||||
Permission.MANAGE_RESULT_IMPORT_URLS.getStringPermission(),
|
||||
Permission.MANAGE_STRUCTURE_IMPORT_URLS.getStringPermission(),
|
||||
Permission.MANAGE_TRACKED_RACES.getStringPermission(),
|
||||
Permission.MANAGE_WIND.getStringPermission(),
|
||||
|
||||
// back-end:
|
||||
Permission.EVENT.getStringPermission(),
|
||||
Permission.REGATTA.getStringPermission(),
|
||||
Permission.LEADERBOARD.getStringPermission(),
|
||||
Permission.LEADERBOARD_GROUP.getStringPermission()
|
||||
);
|
||||
} else {
|
||||
result = Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -15,7 +15,8 @@ Require-Bundle: org.json.simple;bundle-version="1.1.0",
|
||||
com.sap.sailing.domain.shared.android,
|
||||
com.sap.sailing.domain,
|
||||
com.sap.sailing.declination,
|
||||
com.sap.sse.common
|
||||
com.sap.sse.common,
|
||||
com.sap.sse.security
|
||||
Import-Package: javax.ws.rs;version="1.1.1",
|
||||
javax.ws.rs.core;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 com.sap.sse.security.jaxrs.ShiroAuthorizationExceptionTo401ResponseMapper;
|
||||
|
||||
public class RestApiApplication extends Application {
|
||||
public RestApiApplication() {
|
||||
}
|
||||
|
||||
@Override
|
||||
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 }));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,8 @@ Require-Bundle: com.sap.sailing.domain,
|
||||
com.sap.sse.security,
|
||||
org.apache.shiro.core;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",
|
||||
com.sap.sse.security.common
|
||||
Bundle-ClassPath: .
|
||||
Web-ContextPath: /sailingserver
|
||||
Export-Package: com.sap.sailing.server.gateway,
|
||||
|
||||
@@ -286,14 +286,18 @@
|
||||
<servlet-name>Jersey REST SPI</servlet-name>
|
||||
<servlet-class>com.sap.sailing.server.gateway.jaxrs.RestServletContainer</servlet-class>
|
||||
<init-param>
|
||||
<param-name>javax.ws.rs.Application</param-name>
|
||||
<param-value>com.sap.sailing.server.gateway.jaxrs.spi.RestSpiApplication</param-value>
|
||||
<param-name>javax.ws.rs.Application</param-name>
|
||||
<param-value>com.sap.sailing.server.gateway.jaxrs.spi.RestSpiApplication</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
|
||||
<param-value>com.sap.sailing.server.gateway.jaxrs.AccessControlAndEncodingResponseFilter</param-value>
|
||||
</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-mapping>
|
||||
<servlet-name>Jersey REST SPI</servlet-name>
|
||||
|
||||
+1
-4
@@ -34,19 +34,16 @@ public class RestServletContainer extends ServletContainer {
|
||||
@Override
|
||||
public void init(ServletConfig config) throws ServletException {
|
||||
super.init(config);
|
||||
|
||||
BundleContext context = (BundleContext) config.getServletContext().getAttribute(OSGI_RFC66_WEBBUNDLE_BUNDLECONTEXT_NAME);
|
||||
racingEventServiceTracker = new ServiceTracker<RacingEventService, RacingEventService>(context, RacingEventService.class.getName(), null);
|
||||
racingEventServiceTracker.open();
|
||||
|
||||
config.getServletContext().setAttribute(RACING_EVENT_SERVICE_TRACKER_NAME, racingEventServiceTracker);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
super.destroy();
|
||||
|
||||
if(racingEventServiceTracker != null) {
|
||||
if (racingEventServiceTracker != null) {
|
||||
racingEventServiceTracker.close();
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -11,11 +11,13 @@ import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import com.sap.sailing.domain.base.Event;
|
||||
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.server.gateway.jaxrs.AbstractSailingServerResource;
|
||||
import com.sap.sailing.server.gateway.serialization.JsonSerializer;
|
||||
@@ -35,6 +37,7 @@ public class EventsResource extends AbstractSailingServerResource {
|
||||
@GET
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
public Response getEvents() {
|
||||
SecurityUtils.getSubject().checkPermission(Permission.EVENT.getStringPermission(Permission.Mode.READ));
|
||||
JsonSerializer<EventBase> eventSerializer = new EventBaseJsonSerializer(new VenueJsonSerializer(new CourseAreaJsonSerializer()), new LeaderboardGroupBaseJsonSerializer());
|
||||
JSONArray result = new JSONArray();
|
||||
for (EventBase event : getService().getAllEvents()) {
|
||||
@@ -50,6 +53,7 @@ public class EventsResource extends AbstractSailingServerResource {
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
@Path("{eventId}")
|
||||
public Response getEvent(@PathParam("eventId") String eventId) {
|
||||
SecurityUtils.getSubject().checkPermission(Permission.EVENT.getStringPermissionForObjects(Permission.Mode.READ, eventId));
|
||||
Response response;
|
||||
UUID eventUuid;
|
||||
try {
|
||||
@@ -76,6 +80,7 @@ public class EventsResource extends AbstractSailingServerResource {
|
||||
@Path("{eventId}/racestates")
|
||||
public Response getRaceStates(@PathParam("eventId") String eventId, @QueryParam("filterByLeaderboard") String filterByLeaderboard,
|
||||
@QueryParam("filterByCourseArea") String filterByCourseArea, @QueryParam("filterByDayOffset") String filterByDayOffset) {
|
||||
SecurityUtils.getSubject().checkPermission(Permission.EVENT.getStringPermissionForObjects(Permission.Mode.READ, eventId));
|
||||
Response response;
|
||||
UUID eventUuid;
|
||||
try {
|
||||
|
||||
+6
@@ -5,10 +5,13 @@ import java.util.Set;
|
||||
|
||||
import javax.ws.rs.core.Application;
|
||||
|
||||
import com.sap.sse.security.jaxrs.ShiroAuthorizationExceptionTo401ResponseMapper;
|
||||
|
||||
|
||||
public class RestApiApplication extends Application {
|
||||
public Set<Class<?>> getClasses() {
|
||||
HashSet<Class<?>> classes = new HashSet<>();
|
||||
// RESTlets
|
||||
classes.add(LeaderboardGroupsResource.class);
|
||||
classes.add(EventsResource.class);
|
||||
classes.add(RegattasResource.class);
|
||||
@@ -17,6 +20,9 @@ public class RestApiApplication extends Application {
|
||||
classes.add(SearchResource.class);
|
||||
classes.add(GPSFixesResource.class);
|
||||
classes.add(CompetitorsResource.class);
|
||||
|
||||
// Exception Mapper
|
||||
classes.add(ShiroAuthorizationExceptionTo401ResponseMapper.class);
|
||||
return classes;
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -5,11 +5,16 @@ import java.util.Set;
|
||||
|
||||
import javax.ws.rs.core.Application;
|
||||
|
||||
import com.sap.sse.security.jaxrs.ShiroAuthorizationExceptionTo401ResponseMapper;
|
||||
|
||||
|
||||
public class RestSpiApplication extends Application {
|
||||
public Set<Class<?>> getClasses() {
|
||||
HashSet<Class<?>> classes = new HashSet<>();
|
||||
classes.add(MasterDataResource.class);
|
||||
|
||||
// exception mapper
|
||||
classes.add(ShiroAuthorizationExceptionTo401ResponseMapper.class);
|
||||
return classes;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,4 +36,5 @@ Require-Bundle: javax.servlet;bundle-version="2.5.0",
|
||||
com.sap.sse,
|
||||
com.sap.sse.mail
|
||||
Web-ContextPath: /security
|
||||
Export-Package: com.sap.sse.security
|
||||
Export-Package: com.sap.sse.security,
|
||||
com.sap.sse.security.jaxrs
|
||||
|
||||
+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 com.sap.sse.security.jaxrs.ShiroAuthorizationExceptionTo401ResponseMapper;
|
||||
|
||||
public class RestApiApplication extends Application {
|
||||
public Set<Class<?>> getClasses() {
|
||||
HashSet<Class<?>> classes = new HashSet<>();
|
||||
classes.add(SecurityResource.class);
|
||||
|
||||
// exception mapper
|
||||
classes.add(ShiroAuthorizationExceptionTo401ResponseMapper.class);
|
||||
return classes;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user