View Javadoc

1   /*
2    * Copyright 2015 Data Archiving and Networked Services (an institute of
3    * Koninklijke Nederlandse Akademie van Wetenschappen), King's College London,
4    * Georg-August-Universitaet Goettingen Stiftung Oeffentlichen Rechts
5    *
6    * Licensed under the EUPL, Version 1.1 or – as soon they will be approved by
7    * the European Commission - subsequent versions of the EUPL (the "Licence");
8    * You may not use this work except in compliance with the Licence.
9    * You may obtain a copy of the Licence at:
10   *
11   * https://joinup.ec.europa.eu/software/page/eupl
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the Licence is distributed on an "AS IS" basis,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the Licence for the specific language governing
17   * permissions and limitations under the Licence.
18   */
19  
20  package eu.ehri.extension;
21  
22  import eu.ehri.extension.base.AbstractResource;
23  import eu.ehri.project.acl.AclManager;
24  import eu.ehri.project.acl.GlobalPermissionSet;
25  import eu.ehri.project.acl.InheritedGlobalPermissionSet;
26  import eu.ehri.project.acl.InheritedItemPermissionSet;
27  import eu.ehri.project.acl.ItemPermissionSet;
28  import eu.ehri.project.core.Tx;
29  import eu.ehri.project.exceptions.ItemNotFound;
30  import eu.ehri.project.exceptions.PermissionDenied;
31  import eu.ehri.project.models.PermissionGrant;
32  import eu.ehri.project.models.base.Accessible;
33  import eu.ehri.project.models.base.Accessor;
34  import eu.ehri.project.models.base.PermissionScope;
35  import org.neo4j.graphdb.GraphDatabaseService;
36  
37  import javax.ws.rs.Consumes;
38  import javax.ws.rs.GET;
39  import javax.ws.rs.POST;
40  import javax.ws.rs.Path;
41  import javax.ws.rs.PathParam;
42  import javax.ws.rs.Produces;
43  import javax.ws.rs.core.CacheControl;
44  import javax.ws.rs.core.Context;
45  import javax.ws.rs.core.MediaType;
46  import javax.ws.rs.core.Response;
47  
48  /**
49   * Web service resource for setting and reading permissions.
50   */
51  @Path(PermissionsResource.ENDPOINT)
52  public class PermissionsResource extends AbstractResource {
53  
54      public static final String ENDPOINT = "permissions";
55  
56      public PermissionsResource(@Context GraphDatabaseService database) {
57          super(database);
58      }
59  
60      /**
61       * Get the cache control that should be applied to permission
62       * data.
63       *
64       * @return A cache control object
65       */
66      public static CacheControl getCacheControl() {
67          CacheControl cacheControl = new CacheControl();
68          cacheControl.setMaxAge(AbstractResource.ITEM_CACHE_TIME);
69          return cacheControl;
70      }
71  
72      /**
73       * Get the global permission matrix for the user making the request, based
74       * on the Authorization header.
75       *
76       * @return The current user's global permissions
77       */
78      @GET
79      @Produces(MediaType.APPLICATION_JSON)
80      public InheritedGlobalPermissionSet getGlobalMatrix() throws PermissionDenied,
81              ItemNotFound {
82          try (final Tx tx = beginTx()) {
83              InheritedGlobalPermissionSet matrix = getGlobalMatrix(getRequesterUserProfile().getId());
84              tx.success();
85              return matrix;
86          }
87      }
88  
89      /**
90       * Get the global permission matrix for the given accessor.
91       *
92       * @param userId The user ID
93       * @return The user's global permissions
94       */
95      @GET
96      @Produces(MediaType.APPLICATION_JSON)
97      @Path("{userOrGroup:[^/]+}")
98      public InheritedGlobalPermissionSet getGlobalMatrix(@PathParam("userOrGroup") String userId)
99              throws PermissionDenied, ItemNotFound {
100         try (final Tx tx = beginTx()) {
101             Accessor accessor = manager.getEntity(userId, Accessor.class);
102             InheritedGlobalPermissionSet set = api()
103                     .aclManager()
104                     .getInheritedGlobalPermissions(accessor);
105             tx.success();
106             return set;
107         }
108     }
109 
110     /**
111      * Set a user's global permission matrix.
112      *
113      * @param userId  The user ID
114      * @param globals The permission matrix data
115      * @return The new permissions
116      */
117     @POST
118     @Consumes(MediaType.APPLICATION_JSON)
119     @Produces(MediaType.APPLICATION_JSON)
120     @Path("{userOrGroup:[^/]+}")
121     public InheritedGlobalPermissionSet setGlobalMatrix(
122             @PathParam("userOrGroup") String userId,
123             GlobalPermissionSet globals) throws PermissionDenied, ItemNotFound {
124         try (final Tx tx = beginTx()) {
125             Accessor accessor = manager.getEntity(userId, Accessor.class);
126             InheritedGlobalPermissionSet newPerms
127                     = api().acl().setGlobalPermissionMatrix(accessor, globals);
128             tx.success();
129             return newPerms;
130         }
131     }
132 
133     /**
134      * Get the permission matrix for a given user on the given entity.
135      *
136      * @param userId The user's ID
137      * @param id     The item id
138      * @return The user's permissions for that item
139      */
140     @GET
141     @Produces(MediaType.APPLICATION_JSON)
142     @Path("{userOrGroup:[^/]+}/item/{id:[^/]+}")
143     public InheritedItemPermissionSet getEntityMatrix(
144             @PathParam("userOrGroup") String userId,
145             @PathParam("id") String id) throws PermissionDenied, ItemNotFound {
146         try (final Tx tx = beginTx()) {
147             Accessor accessor = manager.getEntity(userId, Accessor.class);
148             Accessible entity = manager.getEntity(id, Accessible.class);
149             AclManager acl = api().withScope(entity.getPermissionScope()).aclManager();
150             InheritedItemPermissionSet set = acl.getInheritedItemPermissions(entity, accessor);
151             tx.success();
152             return set;
153         }
154     }
155 
156     /**
157      * Set a user's permissions on a given item.
158      *
159      * @param id        the item id
160      * @param userId    the user id
161      * @param itemPerms the serialized permission list
162      */
163     @POST
164     @Consumes(MediaType.APPLICATION_JSON)
165     @Produces(MediaType.APPLICATION_JSON)
166     @Path("{userOrGroup:[^/]+}/item/{id:[^/]+}")
167     public InheritedItemPermissionSet setItemPermissions(
168             @PathParam("userOrGroup") String userId,
169             @PathParam("id") String id,
170             ItemPermissionSet itemPerms) throws PermissionDenied, ItemNotFound {
171         try (final Tx tx = beginTx()) {
172             Accessor accessor = manager.getEntity(userId, Accessor.class);
173             Accessible item = manager.getEntity(id, Accessible.class);
174             InheritedItemPermissionSet set = api().acl()
175                     .setItemPermissions(item, accessor, itemPerms.asSet());
176             tx.success();
177             return set;
178         }
179     }
180 
181     /**
182      * Get the user's permissions for a given scope.
183      *
184      * @param userId The user's permissions
185      * @param id     The scope ID
186      * @return The matrix for the given scope
187      */
188     @GET
189     @Produces(MediaType.APPLICATION_JSON)
190     @Path("{userOrGroup:[^/]+}/scope/{id:[^/]+}")
191     public InheritedGlobalPermissionSet getScopedMatrix(@PathParam("userOrGroup") String userId,
192             @PathParam("id") String id) throws PermissionDenied, ItemNotFound {
193         try (final Tx tx = beginTx()) {
194             Accessor accessor = manager.getEntity(userId, Accessor.class);
195             PermissionScope scope = manager.getEntity(id, PermissionScope.class);
196             InheritedGlobalPermissionSet set = api()
197                     .withScope(scope)
198                     .aclManager()
199                     .getInheritedGlobalPermissions(accessor);
200             tx.success();
201             return set;
202         }
203     }
204 
205     /**
206      * Set a user's permissions on a content type with a given scope.
207      *
208      * @param userId  the user
209      * @param id      the scope id
210      * @param globals the serialized permission list
211      * @return The new permission matrix
212      */
213     @POST
214     @Consumes(MediaType.APPLICATION_JSON)
215     @Produces(MediaType.APPLICATION_JSON)
216     @Path("{userOrGroup:[^/]+}/scope/{id:[^/]+}")
217     public InheritedGlobalPermissionSet setScopedPermissions(
218             @PathParam("userOrGroup") String userId,
219             @PathParam("id") String id,
220             GlobalPermissionSet globals) throws PermissionDenied, ItemNotFound {
221         try (final Tx tx = beginTx()) {
222             Accessor accessor = manager.getEntity(userId, Accessor.class);
223             PermissionScope scope = manager.getEntity(id, PermissionScope.class);
224             InheritedGlobalPermissionSet matrix = api()
225                     .withScope(scope)
226                     .acl()
227                     .setGlobalPermissionMatrix(accessor, globals);
228             tx.success();
229             return matrix;
230         }
231     }
232 
233     /**
234      * Get a list of permission grants for the given user
235      *
236      * @param id the user's id
237      * @return a list of permission grants for the user
238      */
239     @GET
240     @Produces(MediaType.APPLICATION_JSON)
241     @Path("{userOrGroup:[^/]+}/permission-grants")
242     public Response listPermissionGrants(@PathParam("userOrGroup") String id) throws ItemNotFound {
243         try (final Tx tx = beginTx()) {
244             Accessor user = manager.getEntity(id, Accessor.class);
245             Response response = streamingPage(() -> getQuery()
246                     .page(user.getPermissionGrants(), PermissionGrant.class));
247             tx.success();
248             return response;
249         }
250     }
251 }