source: AnnotationManagerN4J/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorAnnotations.java @ 105:7417f5915181

tip
Last change on this file since 105:7417f5915181 was 105:7417f5915181, checked in by casties, 7 years ago

check admin permission before changing permissions.
Enum for typesafe actions.

File size: 10.6 KB
Line 
1package de.mpiwg.itgroup.annotations.restlet;
2
3/*
4 * #%L
5 * AnnotationManager
6 * %%
7 * Copyright (C) 2012 - 2014 MPIWG Berlin
8 * %%
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as
11 * published by the Free Software Foundation, either version 3 of the
12 * License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Lesser Public License for more details.
18 *
19 * You should have received a copy of the GNU General Lesser Public
20 * License along with this program.  If not, see
21 * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22 * #L%
23 */
24
25import java.io.IOException;
26import java.io.UnsupportedEncodingException;
27import java.net.URLDecoder;
28import java.util.ArrayList;
29import java.util.List;
30
31import org.json.JSONArray;
32import org.json.JSONException;
33import org.json.JSONObject;
34import org.restlet.data.Form;
35import org.restlet.data.Status;
36import org.restlet.ext.json.JsonRepresentation;
37import org.restlet.representation.Representation;
38import org.restlet.resource.Delete;
39import org.restlet.resource.Get;
40import org.restlet.resource.Post;
41import org.restlet.resource.Put;
42
43import de.mpiwg.itgroup.annotations.Annotation;
44import de.mpiwg.itgroup.annotations.Annotation.Action;
45import de.mpiwg.itgroup.annotations.Person;
46import de.mpiwg.itgroup.annotations.neo4j.AnnotationStore;
47import de.mpiwg.itgroup.annotations.restlet.utils.JSONObjectComparator;
48
49/**
50 * Implements the "annotations" uri of the Annotator API. see
51 * <https://github.com/okfn/annotator/wiki/Storage>
52 *
53 * @author dwinter, casties
54 *
55 */
56public class AnnotatorAnnotations extends AnnotatorResourceImpl {
57
58    /**
59     * GET with JSON content-type.
60     *
61     * @param entity
62     * @return
63     */
64    @Get("json")
65    public Representation doGetJSON(Representation entity) {
66        logger.fine("AnnotatorAnnotations doGetJSON!");
67        // id from URI /annotations/{id}
68        String id = null;
69        String jsonId = (String) getRequest().getAttributes().get("id");
70        if (jsonId != null) {
71            // URL decode
72            try {
73                jsonId = URLDecoder.decode(jsonId, "UTF-8");
74            } catch (UnsupportedEncodingException e) {
75                // this shouldn't happen
76            }
77            id = decodeJsonId(jsonId);
78            logger.fine("annotation-id=" + id);
79        }
80
81        // do authentication
82        Person authUser = getUserFromAuthToken(entity);
83        logger.fine("request authenticated=" + authUser);
84
85        if (id == null) {
86            // no id -- send all annotations
87            Form form = getRequest().getResourceRef().getQueryAsForm();
88            int limit = getInt(form.getFirstValue("limit", "1000"));
89            int offset = getInt(form.getFirstValue("offset", "0"));
90            String sortBy = form.getFirstValue("sortBy");
91            return getAllAnnotations(authUser, limit, offset, sortBy);
92        }
93
94        // send annotation with id
95        AnnotationStore store = getAnnotationStore();
96        Annotation annot = store.getAnnotationById(id);
97        if (annot != null) {
98            if (!annot.isActionAllowed(Action.read, authUser, store)) {
99                setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Not Authorized!");
100                return null;
101            }
102            JSONObject result = createAnnotatorJson(annot, (authUser == null));
103            return new JsonRepresentation(result);
104        } else {
105            // not found
106            setStatus(Status.CLIENT_ERROR_NOT_FOUND);
107            return null;
108        }
109    }
110
111    private Representation getAllAnnotations(Person authUser, int limit, int offset, String sortBy) {
112        AnnotationStore store = getAnnotationStore();
113        ArrayList<JSONObject> results = new ArrayList<JSONObject>();
114
115        // read all annotations
116        List<Annotation> annotations = store.getAnnotations(null, null, 0, 0);
117        for (Annotation annotation : annotations) {
118            // check permission
119            if (!annotation.isActionAllowed(Action.read, authUser, store))
120                continue;
121            // add annotation to list
122            JSONObject jo = createAnnotatorJson(annotation, false);
123            results.add(jo);
124        }
125
126        // sort if necessary
127        if (sortBy != null) {
128            JSONObjectComparator.sortAnnotations(results, sortBy);
129        }
130
131        // put in JSON list
132        JSONArray rows = new JSONArray();
133        int cnt = 0;
134        int max = limit + offset;
135        for (JSONObject result : results) {
136            cnt += 1;
137            if (cnt < offset) continue;
138            rows.put(result);
139            if (limit > 0 && cnt >= max) break;
140        }
141
142        // assemble result object
143        JSONObject result = new JSONObject();
144        try {
145            result.put("rows", rows);
146            result.put("total", rows.length());
147        } catch (JSONException e) {
148            setStatus(Status.SERVER_ERROR_INTERNAL, "JSON Error");
149            return null;
150        }
151        return new JsonRepresentation(result);
152    }
153
154    /**
155     * POST with JSON content-type. Creates a new Annotation.
156     *
157     * @return
158     */
159    @Post("json")
160    public Representation doPostJson(Representation entity) {
161        logger.fine("AnnotatorAnnotations doPostJSON!");
162
163        // do authentication TODO: who's allowed to create?
164        Person authUser = getUserFromAuthToken(entity);
165        logger.fine("request authenticated=" + authUser);
166        if (authUser == null) {
167            setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Not Authorized!");
168            return null;
169        }
170
171        Annotation annot = null;
172        try {
173            JsonRepresentation jrep = new JsonRepresentation(entity);
174            JSONObject jo = jrep.getJsonObject();
175            if (jo == null) {
176                setStatus(Status.SERVER_ERROR_INTERNAL);
177                return null;
178            }
179            // make sure id is not set for POST
180            jo.remove("id");
181            // create Annotation object from posted JSON
182            annot = createAnnotation(jo, entity);
183        } catch (IOException e) {
184                logger.warning(e.toString());
185            setStatus(Status.SERVER_ERROR_INTERNAL);
186            return null;
187        } catch (JSONException e) {
188                logger.warning(e.toString());
189            setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
190            return null;
191        }
192        if (annot == null) {
193            setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
194            return null;
195        }
196        Annotation storedAnnot;
197        // store Annotation
198        storedAnnot = getAnnotationStore().storeAnnotation(annot);
199        /*
200         * according to https://github.com/okfn/annotator/wiki/Storage we should
201         * return 303: see other. For now we return the annotation.
202         */
203        JSONObject jo = createAnnotatorJson(storedAnnot, (authUser == null));
204        JsonRepresentation retRep = new JsonRepresentation(jo);
205        return retRep;
206    }
207
208    /**
209     * PUT with JSON content-type. Modifies an Annotation.
210     *
211     * @param entity
212     * @return
213     */
214    @Put("json")
215    public Representation doPutJSON(Representation entity) {
216        logger.fine("AnnotatorAnnotations doPutJSON!");
217        // id from URI /annotations/{id}
218        String jsonId = (String) getRequest().getAttributes().get("id");
219        String id = decodeJsonId(jsonId);
220        logger.fine("annotation-id=" + id);
221
222        // do authentication
223        Person authUser = getUserFromAuthToken(entity);
224        logger.fine("request authenticated=" + authUser);
225
226        Annotation annot = null;
227        AnnotationStore store = getAnnotationStore();
228        try {
229            JsonRepresentation jrep = new JsonRepresentation(entity);
230            JSONObject jo = jrep.getJsonObject();
231            if (jo == null) {
232                setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
233                return null;
234            }
235            // get stored Annotation
236            Annotation storedAnnot = store.getAnnotationById(id);
237            if (storedAnnot == null) {
238                setStatus(Status.CLIENT_ERROR_NOT_FOUND);
239                return null;
240            }
241            if (!storedAnnot.isActionAllowed(Action.update, authUser, store)) {
242                setStatus(Status.CLIENT_ERROR_FORBIDDEN);
243                return null;
244            }
245            // update from posted JSON
246            annot = updateAnnotation(storedAnnot, jo, entity);
247            // store Annotation
248            storedAnnot = store.storeAnnotation(annot);
249            /*
250             * according to https://github.com/okfn/annotator/wiki/Storage we
251             * should return 303: see other. but the client doesn't like it
252             * setStatus(Status.REDIRECTION_SEE_OTHER); // go to same URL as
253             * this one Reference thisUrl = this.getReference();
254             * this.getResponse().setLocationRef(thisUrl);
255             */
256            // return new annotation
257            jo = createAnnotatorJson(storedAnnot, (authUser == null));
258            JsonRepresentation retRep = new JsonRepresentation(jo);
259            return retRep;
260        } catch (JSONException e) {
261            logger.severe("Error in doPutJSON: "+e);
262            setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
263        } catch (IOException e) {
264            logger.severe("Error in doPutJSON: "+e);
265            setStatus(Status.SERVER_ERROR_INTERNAL, "Other Error");
266        }
267        return null;
268    }
269
270    /**
271     * DELETE with JSON content-type. Deletes an Annotation.
272     *
273     * @param entity
274     * @return
275     */
276    @Delete("json")
277    public Representation doDeleteJSON(Representation entity) {
278        logger.fine("AnnotatorAnnotations doDeleteJSON!");
279        // id from URI /annotations/{id}
280        String jsonId = (String) getRequest().getAttributes().get("id");
281        String id = decodeJsonId(jsonId);
282        logger.fine("annotation-id=" + id);
283
284        // do authentication
285        Person authUser = getUserFromAuthToken(entity);
286        logger.fine("request authenticated=" + authUser);
287        AnnotationStore store = getAnnotationStore();
288        Annotation annot = store.getAnnotationById(id);
289        if (annot != null) {
290            if (!annot.isActionAllowed(Action.delete, authUser, store)) {
291                setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Not Authorized!");
292                return null;
293            }
294        }
295        // delete annotation
296        store.deleteAnnotationById(id);
297        setStatus(Status.SUCCESS_NO_CONTENT);
298        return null;
299    }
300
301}
Note: See TracBrowser for help on using the repository browser.