View Javadoc
1   package de.dlr.shepard.context.collection.services;
2   
3   import de.dlr.shepard.auth.permission.io.PermissionsIO;
4   import de.dlr.shepard.auth.permission.model.Permissions;
5   import de.dlr.shepard.auth.permission.model.Roles;
6   import de.dlr.shepard.auth.permission.services.PermissionsService;
7   import de.dlr.shepard.auth.security.AuthenticationContext;
8   import de.dlr.shepard.auth.users.services.UserService;
9   import de.dlr.shepard.common.exceptions.InvalidAuthException;
10  import de.dlr.shepard.common.exceptions.InvalidPathException;
11  import de.dlr.shepard.common.exceptions.InvalidRequestException;
12  import de.dlr.shepard.common.util.AccessType;
13  import de.dlr.shepard.common.util.Constants;
14  import de.dlr.shepard.common.util.DateHelper;
15  import de.dlr.shepard.common.util.PermissionType;
16  import de.dlr.shepard.common.util.QueryParamHelper;
17  import de.dlr.shepard.context.collection.daos.CollectionDAO;
18  import de.dlr.shepard.context.collection.entities.Collection;
19  import de.dlr.shepard.context.collection.io.CollectionIO;
20  import de.dlr.shepard.context.version.daos.VersionDAO;
21  import de.dlr.shepard.context.version.entities.Version;
22  import jakarta.enterprise.context.RequestScoped;
23  import jakarta.inject.Inject;
24  import java.util.Date;
25  import java.util.List;
26  import java.util.UUID;
27  
28  @RequestScoped
29  public class CollectionService {
30  
31    @Inject
32    CollectionDAO collectionDAO;
33  
34    @Inject
35    UserService userService;
36  
37    @Inject
38    PermissionsService permissionsService;
39  
40    @Inject
41    DateHelper dateHelper;
42  
43    @Inject
44    VersionDAO versionDAO;
45  
46    @Inject
47    AuthenticationContext authenticationContext;
48  
49    /**
50     * Creates a Collection and stores it in Neo4J
51     *
52     * @param collection to be stored
53     * @return the created collection
54     */
55    public Collection createCollection(CollectionIO collection) {
56      Date date = dateHelper.getDate();
57      var user = userService.getCurrentUser();
58  
59      var toCreate = new Collection();
60      toCreate.setAttributes(collection.getAttributes());
61      toCreate.setCreatedBy(user);
62      toCreate.setCreatedAt(date);
63      toCreate.setDescription(collection.getDescription());
64      toCreate.setName(collection.getName());
65      var createdCollection = collectionDAO.createOrUpdate(toCreate);
66  
67      Version nullVersion = new Version(Constants.HEAD, Constants.HEAD_VERSION, date, user);
68      Version savedNullVersion = versionDAO.createOrUpdate(nullVersion);
69  
70      long collectionId = createdCollection.getId();
71      createdCollection.setShepardId(collectionId);
72      createdCollection.setVersion(savedNullVersion);
73      var updated = collectionDAO.createOrUpdate(createdCollection);
74      permissionsService.createPermissions(updated, user, PermissionType.Private);
75  
76      return updated;
77    }
78  
79    /**
80     * Searches the database for all Collections
81     *
82     * @param params encapsulates possible parameters
83     * @param username the name of the user
84     * @return a list of Collections
85     */
86    public List<Collection> getAllCollections(QueryParamHelper params) {
87      List<Collection> queryResult = collectionDAO.findAllCollectionsByShepardId(
88        params,
89        authenticationContext.getCurrentUserName()
90      );
91      List<Collection> collections = queryResult.stream().map(this::cutDeleted).toList();
92      return collections;
93    }
94  
95    /**
96     * Retrieves a collection by shepardId.
97     * The returned collection is in 'light' format, so dataobjects and incoming references are excluded.
98     *
99     * @param shepardId long
100    * @return Collection
101    * @throws InvalidPathException if no collection could be found by shepardId
102    * @throws InvalidAuthException if the user does not have permissions to read the collection
103    */
104   public Collection getCollection(long shepardId) {
105     return getCollection(shepardId, null, true);
106   }
107 
108   /**
109    * Retrieves a collection by shepardId and versionUID.
110    * The returned collection is in 'light' format, so dataobjects and incoming references are excluded.
111    *
112    * @param shepardId long
113    * @param versionUID UUID
114    * @return Collection
115    * @throws InvalidPathException if no collection (with specified version) could be found by shepardId
116    * @throws InvalidAuthException if the user does not have permissions to read the collection
117    */
118   public Collection getCollection(long shepardId, UUID versionUID) {
119     return getCollection(shepardId, versionUID, true);
120   }
121 
122   /**
123    * Fetches a collection including permissions, attributes, contained data objects and incoming references.
124    * @param shepardId shepardId of the desired collection
125    * @return Collection
126    * @throws InvalidPathException if no collection could be found by shepardId
127    * @throws InvalidAuthException if the user does not have permissions to read the collection
128    */
129   public Collection getCollectionWithDataObjectsAndIncomingReferences(long shepardId) {
130     return getCollection(shepardId, null, false);
131   }
132 
133   /**
134    * Fetches a collection including permissions, attributes, contained data objects and incoming references.
135    * @param shepardId shepardId of the desired collection
136    * @param versionUID ID of the version to retrieve
137    * @return Collection
138    * @throws InvalidPathException if no collection could be found by shepardId
139    * @throws InvalidAuthException if the user does not have permissions to read the collection
140    */
141   public Collection getCollectionWithDataObjectsAndIncomingReferences(long shepardId, UUID versionUID) {
142     return getCollection(shepardId, versionUID, false);
143   }
144 
145   /**
146    * Return collection by shepard Id or shepard id + versionUId.
147    *
148    * @return Collection
149    * @throws InvalidPathException if no collection could be found by shepardId
150    * @throws InvalidAuthException if the user does not have permissions to read the collection
151    */
152   private Collection getCollection(long shepardId, UUID versionUID, boolean excludeDataObjectsAndIncomingReferences) {
153     Collection ret;
154     String errorMsg;
155     if (versionUID == null) {
156       ret = collectionDAO.findByShepardId(shepardId, excludeDataObjectsAndIncomingReferences);
157       errorMsg = String.format("Collection with id %s is null or deleted", shepardId);
158     } else {
159       ret = collectionDAO.findByShepardId(shepardId, versionUID, excludeDataObjectsAndIncomingReferences);
160       errorMsg = String.format("Collection with id %s and versionUID %s is null or deleted", shepardId, versionUID);
161     }
162     if (ret == null || ret.isDeleted()) {
163       throw new InvalidPathException("ID ERROR - " + errorMsg);
164     }
165     assertIsAllowedToReadCollection(shepardId);
166     cutDeleted(ret);
167     return ret;
168   }
169 
170   /**
171    * Updates a Collection with new Attributes.
172    *
173    * @param shepardId  collection's shepardID
174    * @param collection which contains the new Attributes
175    * @param username   of the related user
176    * @return updated Collection
177    * @throws InvalidPathException if no collection could be found by shepardId
178    * @throws InvalidAuthException if the user does not have permissions to read or edit the collection
179    */
180   public Collection updateCollectionByShepardId(long shepardId, CollectionIO collection) {
181     Collection old = getCollectionWithDataObjectsAndIncomingReferences(shepardId);
182     assertIsAllowedToEditCollection(shepardId);
183 
184     old.setUpdatedBy(userService.getCurrentUser());
185     old.setUpdatedAt(dateHelper.getDate());
186     old.setAttributes(collection.getAttributes());
187     old.setDescription(collection.getDescription());
188     old.setName(collection.getName());
189 
190     Collection updated = collectionDAO.createOrUpdate(old);
191     cutDeleted(updated);
192     return updated;
193   }
194 
195   /**
196    * Deletes a Collection in Neo4j.
197    * Before a collection is deleted, a check is run to test if collection exists.
198    *
199    * @param shepardId identifies the Collection
200    * @param username  of the related user
201    * @return a boolean to determine if Collection was successfully deleted
202    * @throws InvalidPathException if no collection could be found by shepardId
203    * @throws InvalidAuthException if the user does not have permissions to read or edit the collection
204    */
205   public void deleteCollection(long shepardId) {
206     getCollection(shepardId);
207     assertIsAllowedToEditCollection(shepardId);
208 
209     var date = dateHelper.getDate();
210     var user = userService.getCurrentUser();
211     if (!collectionDAO.deleteCollectionByShepardId(shepardId, user, date)) {
212       throw new InvalidRequestException(String.format("Could not delete Collection with ShepardId %s", shepardId));
213     }
214   }
215 
216   /**
217    * Gets roles for collection specified by id
218    *
219    * @param collectionId
220    * @return Roles
221    * @throws InvalidPathException if collection with collectionId does not exist
222    * @throws InvalidAuthException if user has no read permissions on specified collection
223    */
224   public Roles getCollectionRoles(long collectionId) {
225     getCollection(collectionId);
226 
227     // We can use the collectionId as neo4jId here since permissions are global for all versions and shepardId and neo4jId are equal for the head version.
228     return permissionsService.getUserRolesOnEntity(collectionId, authenticationContext.getCurrentUserName());
229   }
230 
231   /**
232    * Gets Permissions for collection specified by id
233    *
234    * @param collectionId
235    * @return Permissions
236    * @throws InvalidPathException if collection with collectionId does not exist
237    * @throws InvalidAuthException if user has no read permissions on specified collection, or is not allowed to manage permissions on collection
238    */
239   public Permissions getCollectionPermissions(long collectionId) {
240     getCollection(collectionId);
241     assertIsAllowedToManageCollection(collectionId);
242 
243     // We can use the collectionId as neo4jId here since permissions are global for all versions and shepardId and neo4jId are equal for the head version.
244     return permissionsService.getPermissionsOfEntity(collectionId);
245   }
246 
247   /**
248    * Updates Permissions for collection specified by id
249    *
250    * @param collectionId
251    * @return Permissions
252    * @throws InvalidPathException if collection with collectionId does not exist
253    * @throws InvalidAuthException if user has no read permissions on specified collection, or is not allowed to manage permissions on collection
254    */
255   public Permissions updateCollectionPermissions(PermissionsIO newPermissions, long collectionId) {
256     getCollection(collectionId);
257     assertIsAllowedToManageCollection(collectionId);
258 
259     // We can use the collectionId as neo4jId here since permissions are global for all versions and shepardId and neo4jId are equal for the head version.
260     return permissionsService.updatePermissionsByNeo4jId(newPermissions, collectionId);
261   }
262 
263   /**
264    * Checks if the user requested the Collection is allowed to read it
265    *
266    * @throws InvalidAuthException when user is not allowed to read the Collection
267    */
268   public void assertIsAllowedToReadCollection(long collectionId) {
269     if (
270       !permissionsService.isAccessTypeAllowedForUser(
271         collectionId,
272         AccessType.Read,
273         authenticationContext.getCurrentUserName()
274       )
275     ) {
276       throw new InvalidAuthException("The requested action is forbidden by the permission policies");
277     }
278   }
279 
280   /**
281    * Checks if the user requested the Collection is allowed to edit it
282    *
283    * @throws InvalidAuthException when user is not allowed to edit the Collection
284    */
285   public void assertIsAllowedToEditCollection(long collectionId) {
286     if (
287       !permissionsService.isAccessTypeAllowedForUser(
288         collectionId,
289         AccessType.Write,
290         authenticationContext.getCurrentUserName()
291       )
292     ) {
293       throw new InvalidAuthException("The requested action is forbidden by the permission policies");
294     }
295   }
296 
297   /**
298    * Checks if the user requested the Collection is allowed to manage it
299    *
300    * @throws InvalidAuthException when user is not allowed to manage the Collection
301    */
302   public void assertIsAllowedToManageCollection(long collectionId) {
303     if (
304       !permissionsService.isAccessTypeAllowedForUser(
305         collectionId,
306         AccessType.Manage,
307         authenticationContext.getCurrentUserName()
308       )
309     ) {
310       throw new InvalidAuthException("The requested action is forbidden by the permission policies");
311     }
312   }
313 
314   private Collection cutDeleted(Collection collection) {
315     var dataObjects = collection.getDataObjects().stream().filter(d -> !d.isDeleted()).toList();
316     collection.setDataObjects(dataObjects);
317     return collection;
318   }
319 }