View Javadoc
1   package de.dlr.shepard.data.file.services;
2   
3   import de.dlr.shepard.auth.permission.services.PermissionsService;
4   import de.dlr.shepard.auth.users.entities.User;
5   import de.dlr.shepard.auth.users.services.UserService;
6   import de.dlr.shepard.common.exceptions.InvalidAuthException;
7   import de.dlr.shepard.common.exceptions.InvalidPathException;
8   import de.dlr.shepard.common.mongoDB.NamedInputStream;
9   import de.dlr.shepard.common.util.DateHelper;
10  import de.dlr.shepard.common.util.PermissionType;
11  import de.dlr.shepard.common.util.QueryParamHelper;
12  import de.dlr.shepard.data.AbstractContainerService;
13  import de.dlr.shepard.data.file.daos.FileContainerDAO;
14  import de.dlr.shepard.data.file.entities.FileContainer;
15  import de.dlr.shepard.data.file.entities.ShepardFile;
16  import de.dlr.shepard.data.file.io.FileContainerIO;
17  import io.quarkus.logging.Log;
18  import jakarta.enterprise.context.RequestScoped;
19  import jakarta.inject.Inject;
20  import jakarta.ws.rs.InternalServerErrorException;
21  import java.io.InputStream;
22  import java.text.SimpleDateFormat;
23  import java.util.List;
24  import java.util.stream.Collectors;
25  
26  @RequestScoped
27  public class FileContainerService extends AbstractContainerService<FileContainer, FileContainerIO> {
28  
29    @Inject
30    FileContainerDAO fileContainerDAO;
31  
32    @Inject
33    UserService userService;
34  
35    @Inject
36    DateHelper dateHelper;
37  
38    @Inject
39    FileService fileService;
40  
41    @Inject
42    PermissionsService permissionsService;
43  
44    /**
45     * Creates a FileContainer and stores it in Neo4J
46     *
47     * @param fileContainerIO to be stored
48     * @param username        of the related user
49     * @return the created FileContainer
50     */
51    @Override
52    public FileContainer createContainer(FileContainerIO fileContainerIO) {
53      User user = userService.getCurrentUser();
54      FileContainer toCreate = new FileContainer();
55      toCreate.setCreatedAt(dateHelper.getDate());
56      toCreate.setCreatedBy(user);
57      toCreate.setMongoId(fileService.createFileContainer());
58      toCreate.setName(fileContainerIO.getName());
59  
60      var created = fileContainerDAO.createOrUpdate(toCreate);
61      permissionsService.createPermissions(created, user, PermissionType.Private);
62      return created;
63    }
64  
65    /**
66     * Gets the FileContainer
67     *
68     * @param id identifies the searched FileContainer
69     * @return the FileContainer with matching id or null
70     * @throws InvalidPathException if the file container cannot be found
71     * @throws InvalidAuthException if user has no read permission on container
72     */
73    @Override
74    public FileContainer getContainer(long id) {
75      FileContainer fileContainer = fileContainerDAO.findByNeo4jId(id);
76  
77      if (fileContainer == null || fileContainer.isDeleted()) {
78        String errorMsg = String.format("ID ERROR - File Container with id %s is null or deleted", id);
79        Log.errorf(errorMsg);
80        throw new InvalidPathException(errorMsg);
81      }
82      assertIsAllowedToReadContainer(id);
83      fileContainer.setCollectionList(fileContainer.getCollectionList().stream().filter(d -> !d.isDeleted()).toList());
84      return fileContainer;
85    }
86  
87    /**
88     * Searches the database for all FileContainers
89     *
90     * @param params   QueryParamsHelper
91     * @param username the name of the user
92     * @return a list of FileContainers
93     */
94    @Override
95    public List<FileContainer> getAllContainers(QueryParamHelper params) {
96      User user = userService.getCurrentUser();
97      List<FileContainer> containers = fileContainerDAO.findAllFileContainers(params, user.getUsername());
98  
99      // this mapping is done because 'findAllFileContainers' does not return all relations of a container
100     // therefore the returned list of collection ids is ALWAYS empty, even though the container might be set as the default container by a collection
101     // this can lead to confusion
102     // by nullifying the collection id list, it is not included in the API response
103     containers = containers.stream().map(this::nullifyEmptyCollectionIdList).collect(Collectors.toList());
104     return containers;
105   }
106 
107   private FileContainer nullifyEmptyCollectionIdList(FileContainer fileContainer) {
108     if (fileContainer.getCollectionList().isEmpty()) {
109       fileContainer.setCollectionList(null);
110     }
111     return fileContainer;
112   }
113 
114   /**
115    * Deletes a FileContainer in Neo4j
116    *
117    * @param fileContainerId identifies the FileContainer
118    * @param username        the deleting user
119    * @throws InvalidPathException if the file container cannot be found
120    * @throws InvalidAuthException if user has no write permission on container
121    */
122   @Override
123   public void deleteContainer(long fileContainerId) {
124     User user = userService.getCurrentUser();
125     FileContainer fileContainer = getContainer(fileContainerId);
126     assertIsAllowedToDeleteContainer(fileContainerId);
127 
128     String mongoId = fileContainer.getMongoId();
129     fileContainer.setDeleted(true);
130     fileContainer.setUpdatedAt(dateHelper.getDate());
131     fileContainer.setUpdatedBy(user);
132     fileContainerDAO.createOrUpdate(fileContainer);
133     fileService.deleteFileContainer(mongoId);
134   }
135 
136   /**
137    * Get file payload
138    *
139    * @param fileContainerId The container to get the payload from
140    * @param oid             The specific file
141    * @return a NamedInputStream
142    * @throws InvalidPathException if the file container cannot be found
143    * @throws InvalidAuthException if user has no read permission on container
144    */
145   public NamedInputStream getFile(long fileContainerId, String oid) {
146     FileContainer container = getContainer(fileContainerId);
147 
148     return fileService.getPayload(container.getMongoId(), oid);
149   }
150 
151   /**
152    * Create a new file
153    *
154    * @param fileContainerId identifies the file container
155    * @param fileName        the name of the new file
156    * @param inputStream     the file itself
157    * @return The newly created file
158    * @throws InternalServerErrorException if file creation fails
159    * @throws InvalidPathException if the file container cannot be found
160    * @throws InvalidAuthException if user has no read or write permission on container
161    */
162   public ShepardFile createFile(long fileContainerId, String fileName, InputStream inputStream) {
163     FileContainer fileContainer = getContainer(fileContainerId);
164     assertIsAllowedToEditContainer(fileContainerId);
165 
166     if (fileName == null || fileName.isBlank()) {
167       var sdf = new SimpleDateFormat("yyyyMMdd-HHmmss");
168       var dateStr = sdf.format(dateHelper.getDate());
169       fileName = "shepard-file-" + dateStr;
170     }
171 
172     ShepardFile result = fileService.createFile(fileContainer.getMongoId(), fileName, inputStream);
173 
174     fileContainer.addFile(result);
175     fileContainerDAO.createOrUpdate(fileContainer);
176     return result;
177   }
178 
179   /**
180    * Delete one file
181    *
182    * @param fileContainerId The container to get the payload from
183    * @param oid             The specific file
184    
185    */
186   public void deleteFile(long fileContainerId, String oid) {
187     FileContainer container = getContainer(fileContainerId);
188     assertIsAllowedToEditContainer(fileContainerId);
189 
190     fileService.deleteFile(container.getMongoId(), oid);
191 
192     List<ShepardFile> newFiles = container.getFiles().stream().filter(f -> !f.getOid().equals(oid)).toList();
193     container.setFiles(newFiles);
194     fileContainerDAO.createOrUpdate(container);
195   }
196 }