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

Last change on this file since 4173 was 4173, checked in by olhsha, 10 years ago

lintegrity unit test reconstructed so it does not mock any more. getAnnotation works (the others are "ignored"). Needs refactoring (the subdirectory with beans and DummySecurityFilter? class.

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