source: DASISH/t5.6/backend/annotator-backend/trunk/annotator-backend/src/main/java/eu/dasish/annotation/backend/rest/AnnotationResource.java @ 4013

Last change on this file since 4013 was 4013, checked in by olhsha, 11 years ago

implementing authentication=provider as a database, using approach 2 from http://docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#ns-auth-providers, and constructing the security Db as in http://docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#db_schema_users_authorities

File size: 18.3 KB
Line 
1/*
2 * Copyright (C) 2013 DASISH
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17 */
18package eu.dasish.annotation.backend.rest;
19
20import eu.dasish.annotation.backend.BackendConstants;
21import eu.dasish.annotation.backend.dao.DBIntegrityService;
22import eu.dasish.annotation.schema.Annotation;
23import eu.dasish.annotation.schema.AnnotationActionName;
24import eu.dasish.annotation.schema.AnnotationInfoList;
25import eu.dasish.annotation.schema.Action;
26import eu.dasish.annotation.schema.ActionList;
27import eu.dasish.annotation.schema.ObjectFactory;
28import eu.dasish.annotation.schema.Permission;
29import eu.dasish.annotation.schema.PermissionActionName;
30import eu.dasish.annotation.schema.UserWithPermissionList;
31import eu.dasish.annotation.schema.ReferenceList;
32import eu.dasish.annotation.schema.ResponseBody;
33import java.io.IOException;
34import java.sql.Timestamp;
35import java.util.ArrayList;
36import java.util.List;
37import java.util.UUID;
38import javax.servlet.http.HttpServletRequest;
39import javax.servlet.http.HttpServletResponse;
40import javax.ws.rs.Consumes;
41import javax.ws.rs.DELETE;
42import javax.ws.rs.GET;
43import javax.ws.rs.POST;
44import javax.ws.rs.PUT;
45import javax.ws.rs.Path;
46import javax.ws.rs.PathParam;
47import javax.ws.rs.Produces;
48import javax.ws.rs.QueryParam;
49import javax.ws.rs.core.Context;
50import javax.ws.rs.core.MediaType;
51import javax.ws.rs.core.UriInfo;
52import javax.ws.rs.ext.Providers;
53import javax.xml.bind.JAXBElement;
54import org.springframework.beans.factory.annotation.Autowired;
55import org.springframework.security.access.annotation.Secured;
56import org.springframework.stereotype.Component;
57import org.slf4j.Logger;
58import org.slf4j.LoggerFactory;
59
60/**
61 *
62 * @author olhsha
63 */
64@Component
65@Path("/annotations")
66public class AnnotationResource {
67
68    @Autowired
69    private DBIntegrityService dbIntegrityService;
70    @Context
71    private HttpServletRequest httpServletRequest;
72    @Context
73    private HttpServletResponse httpServletResponse;
74    @Context
75    private UriInfo uriInfo;
76    @Context
77    private Providers providers;
78    final String default_permission = "reader";
79    private static final Logger logger = LoggerFactory.getLogger(AnnotationResource.class);
80
81    public void setUriInfo(UriInfo uriInfo) {
82        this.uriInfo = uriInfo;
83    }
84
85    public void setHttpServletResponse(HttpServletResponse httpServletResponse) {
86        this.httpServletResponse = httpServletResponse;
87    }
88
89    public void setHttpServletRequest(HttpServletRequest httpServletRequest) {
90        this.httpServletRequest = httpServletRequest;
91    }
92
93    public void setProviders(Providers providers) {
94        this.providers = providers;
95    }
96
97    public AnnotationResource() {
98    }
99
100    @GET
101    @Produces(MediaType.TEXT_XML)
102    @Path("{annotationid: " + BackendConstants.regExpIdentifier + "}")
103    @Secured("ROLE_USER")
104    public JAXBElement<Annotation> getAnnotation(@PathParam("annotationid") String ExternalIdentifier) {
105        dbIntegrityService.setServiceURI(uriInfo.getBaseUri().toString());
106        final Number annotationID = dbIntegrityService.getAnnotationInternalIdentifier(UUID.fromString(ExternalIdentifier));
107        final Number userID = dbIntegrityService.getUserInternalIDFromRemoteID(httpServletRequest.getRemoteUser());
108        if (canRead(userID, annotationID)) {
109            final Annotation annotation = dbIntegrityService.getAnnotation(annotationID);
110            JAXBElement<Annotation> rootElement = new ObjectFactory().createAnnotation(annotation);
111            logger.info("getAnnotation method: OK");
112            return rootElement;
113        } else {
114            try {
115                logger.error("FORBIDDEN-access attempt");
116                httpServletResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
117            } catch (IOException ioe) {
118                logger.error("IOException: Cannot send server respond about unaithorized access.");
119            }
120            return null;
121        }
122
123    }
124
125    //TODO: unit test
126    @GET
127    @Produces(MediaType.TEXT_XML)
128    @Path("{annotationid: " + BackendConstants.regExpIdentifier + "}/targets")
129    @Secured("ROLE_USER")
130    public JAXBElement<ReferenceList> getAnnotationTargets(@PathParam("annotationid") String ExternalIdentifier) {
131        dbIntegrityService.setServiceURI(uriInfo.getBaseUri().toString());
132        final Number annotationID = dbIntegrityService.getAnnotationInternalIdentifier(UUID.fromString(ExternalIdentifier));
133        final Number userID = dbIntegrityService.getUserInternalIDFromRemoteID(httpServletRequest.getRemoteUser());
134        if (canRead(userID, annotationID)) {
135            final ReferenceList TargetList = dbIntegrityService.getAnnotationTargets(annotationID);
136            logger.info("getAnnotationTargets method: OK");
137            return new ObjectFactory().createTargetList(TargetList);
138        } else {
139            try {
140                logger.error("FORBIDDEN-access attempt");
141                httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
142            } catch (IOException ioe) {
143                logger.error("IOException: Cannot send server respond about unaithorized access.");
144            }
145            return null;
146        }
147    }
148
149    // TODO Unit test
150    @GET
151    @Produces(MediaType.TEXT_XML)
152    @Path("")
153    @Secured("ROLE_USER")
154    public JAXBElement<AnnotationInfoList> getFilteredAnnotations(@QueryParam("link") String link,
155            @QueryParam("text") String text,
156            @QueryParam("access") String permission,
157            @QueryParam("namespace") String namespace,
158            @QueryParam("owner") String ownerExternalId,
159            @QueryParam("after") Timestamp after,
160            @QueryParam("before") Timestamp before) {
161
162        dbIntegrityService.setServiceURI(uriInfo.getBaseUri().toString());
163        Number userID = dbIntegrityService.getUserInternalIDFromRemoteID(httpServletRequest.getRemoteUser());
164        UUID ownerExternalUUID = (ownerExternalId != null) ? UUID.fromString(ownerExternalId) : null;
165        String access = (permission != null) ? permission : default_permission;
166        final AnnotationInfoList annotationInfoList = dbIntegrityService.getFilteredAnnotationInfos(link, text, userID, access, namespace, ownerExternalUUID, after, before);
167        logger.info("getFilteredAnnotations method: OK");
168        return new ObjectFactory().createAnnotationInfoList(annotationInfoList);
169    }
170
171    // TODO Unit test   
172    @GET
173    @Produces(MediaType.TEXT_XML)
174    @Path("{annotationid: " + BackendConstants.regExpIdentifier + "}/permissions")
175    @Secured("ROLE_USER")
176    public JAXBElement<UserWithPermissionList> getAnnotationPermissions(@PathParam("annotationid") String ExternalIdentifier) {
177        dbIntegrityService.setServiceURI(uriInfo.getBaseUri().toString());
178        final Number annotationID = dbIntegrityService.getAnnotationInternalIdentifier(UUID.fromString(ExternalIdentifier));
179        final Number userID = dbIntegrityService.getUserInternalIDFromRemoteID(httpServletRequest.getRemoteUser());
180        if (canRead(userID, annotationID)) {
181            final UserWithPermissionList permissionList = dbIntegrityService.getPermissionsForAnnotation(annotationID);
182            logger.info("getAnnotationPermissions method: OK");
183            return new ObjectFactory().createPermissionList(permissionList);
184        } else {
185            try {
186                logger.error("FORBIDDEN-access attempt");
187                httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
188            } catch (IOException ioe) {
189                logger.error("IOException: Cannot send server respond about unaithorized access.");
190            }
191            return null;
192        }
193
194    }
195
196    ///////////////////////////////////////////////////////
197    // TODO: how to return the status code?
198    @DELETE
199    @Path("{annotationid: " + BackendConstants.regExpIdentifier + "}")
200    @Secured("ROLE_USER")
201    public String deleteAnnotation(@PathParam("annotationid") String externalIdentifier) {
202        dbIntegrityService.setServiceURI(uriInfo.getBaseUri().toString());
203        final Number annotationID = dbIntegrityService.getAnnotationInternalIdentifier(UUID.fromString(externalIdentifier));
204        final Number userID = dbIntegrityService.getUserInternalIDFromRemoteID(httpServletRequest.getRemoteUser());
205        if (isOwner(userID, annotationID)) {
206            int[] resultDelete = dbIntegrityService.deleteAnnotation(annotationID);
207            String result = Integer.toString(resultDelete[0]);
208            logger.info("deleteAnnotation method: OK");
209            return result + " annotation(s) deleted.";
210        } else {
211            logger.error("FORBIDDEN-access attempt. Only the owner can delete an annotation.");
212            try {
213                httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
214            } catch (IOException ioe) {
215                logger.error("IOException: Cannot send server respond about unaithorized access.");
216            }
217            return null;
218        }
219
220    }
221
222    ///////////////////////////////////////////////////////
223    @POST
224    @Consumes(MediaType.APPLICATION_XML)
225    @Produces(MediaType.APPLICATION_XML)
226    @Path("")
227    @Secured("ROLE_USER")
228    public JAXBElement<ResponseBody> createAnnotation(Annotation annotation) {
229        dbIntegrityService.setServiceURI(uriInfo.getBaseUri().toString());
230        final Number userID = dbIntegrityService.getUserInternalIDFromRemoteID(httpServletRequest.getRemoteUser());
231        Number annotationID = dbIntegrityService.addUsersAnnotation(userID, annotation);
232        logger.info("createAnnotation method: OK");
233        return new ObjectFactory().createResponseBody(makeAnnotationResponseEnvelope(annotationID));
234    }
235
236    ///////////////////////////////////////////////////////
237    // TODO: unit test
238    @PUT
239    @Consumes(MediaType.APPLICATION_XML)
240    @Produces(MediaType.APPLICATION_XML)
241    @Path("{annotationid: " + BackendConstants.regExpIdentifier + "}")
242    @Secured("ROLE_USER")
243    public JAXBElement<ResponseBody> updateAnnotation(@PathParam("annotationid") String externalIdentifier, Annotation annotation) {
244        String path = uriInfo.getBaseUri().toString();
245        dbIntegrityService.setServiceURI(path);
246        String annotationURI = annotation.getURI();
247        if (!(path + "annotations/" + externalIdentifier).equals(annotationURI)) {
248            logger.error("Wrong request: the external annotation ID and the annotation ID from the request body do not match.");
249            logger.error("Will do nothing.");
250            return null;
251        }
252        final Number annotationID = dbIntegrityService.getAnnotationInternalIdentifier(UUID.fromString(externalIdentifier));
253        final Number userID = dbIntegrityService.getUserInternalIDFromRemoteID(httpServletRequest.getRemoteUser());
254        if (canWrite(userID, annotationID)) {
255            int updatedRows = dbIntegrityService.updateUsersAnnotation(userID, annotation);
256            logger.info("updateAnnotation method: OK");
257            return new ObjectFactory().createResponseBody(makeAnnotationResponseEnvelope(annotationID));
258
259        } else {
260            logger.error("FORBIDDEN-access attempt.");
261            logger.error("The logged-in user is not authorised to alter this annotation. ");
262            try {
263                httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
264            } catch (IOException ioe) {
265                logger.error("IOException: Cannot send server respond about unaithorized access.");
266            }
267            return null;
268        }
269
270    }
271
272    @PUT
273    @Consumes(MediaType.APPLICATION_XML)
274    @Produces(MediaType.APPLICATION_XML)
275    @Path("{annotationid: " + BackendConstants.regExpIdentifier + "}/permissions/{userid: " + BackendConstants.regExpIdentifier + "}")
276    @Secured("ROLE_USER")
277    public String updatePermission(@PathParam("annotationid") String annotationExternalId, @PathParam("userid") String userExternalId, Permission permission) {
278        dbIntegrityService.setServiceURI(uriInfo.getBaseUri().toString());
279        final Number annotationID = dbIntegrityService.getAnnotationInternalIdentifier(UUID.fromString(annotationExternalId));
280        final Number remoteUserID = dbIntegrityService.getUserInternalIDFromRemoteID(httpServletRequest.getRemoteUser());
281        final Number userID = dbIntegrityService.getUserInternalIdentifier(UUID.fromString(userExternalId));
282        if (isOwner(remoteUserID, annotationID)) {
283            int result = (dbIntegrityService.getPermission(annotationID, userID) != null)
284                    ? dbIntegrityService.updateAnnotationPrincipalPermission(annotationID, userID, permission)
285                    : dbIntegrityService.addAnnotationPrincipalPermission(annotationID, userID, permission);
286            logger.info("updatePermission method: OK");
287            return result + " rows are updated/added";
288
289        } else {
290            logger.error("FORBIDDEN-access attempt");
291            logger.error("The logged-in user is not authorised to alter this annotation. ");
292            try {
293                httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
294            } catch (IOException ioe) {
295                logger.error("IOException: Cannot send server respond about unaithorized access.");
296            }
297            return null;
298        }
299    }
300
301    @PUT
302    @Consumes(MediaType.APPLICATION_XML)
303    @Produces(MediaType.APPLICATION_XML)
304    @Path("{annotationid: " + BackendConstants.regExpIdentifier + "}/permissions/")
305    @Secured("ROLE_USER")
306    public JAXBElement<ResponseBody> updatePermissions(@PathParam("annotationid") String annotationExternalId, UserWithPermissionList permissions) {
307        dbIntegrityService.setServiceURI(uriInfo.getBaseUri().toString());
308        final Number annotationID = dbIntegrityService.getAnnotationInternalIdentifier(UUID.fromString(annotationExternalId));
309        final Number remoteUserID = dbIntegrityService.getUserInternalIDFromRemoteID(httpServletRequest.getRemoteUser());
310        if (isOwner(remoteUserID, annotationID)) {
311            int updatedRows = dbIntegrityService.updatePermissions(annotationID, permissions);
312            logger.info("updatePermissions method: OK");
313            return new ObjectFactory().createResponseBody(makePermissionResponseEnvelope(annotationID));
314        } else {
315            logger.error("FORBIDDEN-access attempt");
316            logger.error("The logged-in user is not authorised to alter this annotation. ");
317            try {
318                httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
319            } catch (IOException ioe) {
320                logger.error("IOException: Cannot send server respond about unaithorized access.");
321            }
322            return null;
323        }
324    }
325
326    /////////////////////////////////////////
327    private ResponseBody makeAnnotationResponseEnvelope(Number annotationID) {
328        ResponseBody result = new ResponseBody();
329        result.setPermissions(null);
330        Annotation annotation = dbIntegrityService.getAnnotation(annotationID);
331        result.setAnnotation(annotation);
332        List<String> targetsNoCached = dbIntegrityService.getTargetsWithNoCachedRepresentation(annotationID);
333        ActionList actionList = new ActionList();
334        result.setActionList(actionList);
335        actionList.getAction().addAll(makeActionList(targetsNoCached, AnnotationActionName.CREATE_CACHED_REPRESENTATION.value()));
336        return result;
337    }
338
339    /////////////////////////////////////////
340    private ResponseBody makePermissionResponseEnvelope(Number annotationID) {
341        ResponseBody result = new ResponseBody();
342        result.setAnnotation(null);
343        UserWithPermissionList permissions = dbIntegrityService.getPermissionsForAnnotation(annotationID);
344        result.setPermissions(permissions);
345        List<String> usersWithNoInfo = dbIntegrityService.getUsersWithNoInfo(annotationID);
346        ActionList actionList = new ActionList();
347        result.setActionList(actionList);
348        actionList.getAction().addAll(makeActionList(usersWithNoInfo, PermissionActionName.PROVIDE_USER_INFO.value()));
349        return result;
350    }
351
352    private List<Action> makeActionList(List<String> resourceURIs, String message) {
353        if (resourceURIs != null) {
354            if (resourceURIs.isEmpty()) {
355                return (new ArrayList<Action>());
356            } else {
357                List<Action> result = new ArrayList<Action>();
358                for (String resourceURI : resourceURIs) {
359                    Action action = new Action();
360                    result.add(action);
361                    action.setMessage(message);
362                    action.setObject(resourceURI);
363                }
364                return result;
365            }
366        } else {
367            return null;
368        }
369    }
370
371    private boolean canRead(Number userID, Number annotationID) {
372        final Permission permission = dbIntegrityService.getPermission(annotationID, userID);
373        if (permission != null) {
374            return (permission.value() == Permission.OWNER.value() || permission.value() == Permission.WRITER.value() || permission.value() == Permission.READER.value());
375        } else {
376            return false;
377        }
378    }
379
380    private boolean canWrite(Number userID, Number annotationID) {
381        final Permission permission = dbIntegrityService.getPermission(annotationID, userID);
382        if (permission != null) {
383            return (permission.value() == Permission.OWNER.value() || permission.value() == Permission.WRITER.value());
384        } else {
385            return false;
386        }
387    }
388
389    private boolean isOwner(Number userID, Number annotationID) {
390        final Permission permission = dbIntegrityService.getPermission(annotationID, userID);
391        if (permission != null) {
392            return (permission.value() == Permission.OWNER.value());
393        } else {
394            return false;
395        }
396    }
397}
Note: See TracBrowser for help on using the repository browser.