-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
268bfa0
commit 6c58421
Showing
40 changed files
with
444 additions
and
47 deletions.
There are no files selected for viewing
2 changes: 1 addition & 1 deletion
2
...ollab/web/rest/ActivityLogController.java → ...lab/controller/ActivityLogController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...es/collab/web/rest/CommentController.java → .../collab/controller/CommentController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...llab/web/rest/NotificationController.java → ...ab/controller/NotificationController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
75 changes: 75 additions & 0 deletions
75
commons/src/main/java/io/flowinquiry/modules/fss/controller/EntityAttachmentController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package io.flowinquiry.modules.fss.controller; | ||
|
||
import io.flowinquiry.modules.fss.domain.EntityAttachment; | ||
import io.flowinquiry.modules.fss.service.EntityAttachmentService; | ||
import io.flowinquiry.modules.fss.service.dto.EntityAttachmentDTO; | ||
import java.util.List; | ||
import org.springframework.http.MediaType; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.DeleteMapping; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
import org.springframework.web.bind.annotation.RequestPart; | ||
import org.springframework.web.bind.annotation.RestController; | ||
import org.springframework.web.multipart.MultipartFile; | ||
|
||
@RestController | ||
@RequestMapping("/api/entity-attachments") | ||
public class EntityAttachmentController { | ||
|
||
private final EntityAttachmentService attachmentService; | ||
|
||
public EntityAttachmentController(EntityAttachmentService attachmentService) { | ||
this.attachmentService = attachmentService; | ||
} | ||
|
||
/** | ||
* Upload multiple attachments and associate them with a specific entity. | ||
* | ||
* @param entityType The type of entity (e.g., "team_request", "comment"). | ||
* @param entityId The ID of the entity. | ||
* @param files The list of files to upload. | ||
* @return A list of saved attachment entities. | ||
*/ | ||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE) | ||
public ResponseEntity<List<EntityAttachment>> uploadAttachments( | ||
@RequestParam("entityType") String entityType, | ||
@RequestParam("entityId") Long entityId, | ||
@RequestPart("files") MultipartFile[] files) | ||
throws Exception { | ||
List<EntityAttachment> attachments = | ||
attachmentService.uploadAttachments(entityType, entityId, files); | ||
return ResponseEntity.ok(attachments); | ||
} | ||
|
||
/** | ||
* Retrieve all attachments for a specific entity. | ||
* | ||
* @param entityType The type of entity (e.g., "team_request", "comment"). | ||
* @param entityId The ID of the entity. | ||
* @return A list of attachments for the specified entity. | ||
*/ | ||
@GetMapping | ||
public ResponseEntity<List<EntityAttachmentDTO>> getAttachments( | ||
@RequestParam("entityType") String entityType, | ||
@RequestParam("entityId") Long entityId) { | ||
List<EntityAttachmentDTO> attachments = | ||
attachmentService.getAttachments(entityType, entityId); | ||
return ResponseEntity.ok(attachments); | ||
} | ||
|
||
/** | ||
* Deletes an attachment by its ID. | ||
* | ||
* @param attachmentId The ID of the attachment to delete. | ||
* @return A ResponseEntity indicating the result of the deletion. | ||
*/ | ||
@DeleteMapping("/{attachmentId}") | ||
public ResponseEntity<Void> deleteAttachment(@PathVariable("attachmentId") Long attachmentId) { | ||
attachmentService.deleteAttachment(attachmentId); | ||
return ResponseEntity.noContent().build(); | ||
} | ||
} |
2 changes: 1 addition & 1 deletion
2
.../fss/web/rest/FileDownloadController.java → ...ss/controller/FileDownloadController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
commons/src/main/java/io/flowinquiry/modules/fss/domain/EntityAttachment.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package io.flowinquiry.modules.fss.domain; | ||
|
||
import jakarta.persistence.Column; | ||
import jakarta.persistence.Entity; | ||
import jakarta.persistence.GeneratedValue; | ||
import jakarta.persistence.GenerationType; | ||
import jakarta.persistence.Id; | ||
import jakarta.persistence.PrePersist; | ||
import jakarta.persistence.Table; | ||
import jakarta.persistence.UniqueConstraint; | ||
import java.time.LocalDateTime; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.EqualsAndHashCode; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import lombok.Setter; | ||
|
||
@Entity | ||
@Table( | ||
name = "fw_entity_attachment", | ||
uniqueConstraints = | ||
@UniqueConstraint(columnNames = {"entity_type", "entity_id", "file_url"})) | ||
@Getter | ||
@Setter | ||
@Builder | ||
@EqualsAndHashCode(onlyExplicitlyIncluded = true) | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
public class EntityAttachment { | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
@EqualsAndHashCode.Include | ||
@Column(name = "entity_type", nullable = false, length = 50) | ||
private String entityType; | ||
|
||
@EqualsAndHashCode.Include | ||
@Column(name = "entity_id", nullable = false) | ||
private Long entityId; | ||
|
||
@Column(name = "file_name", nullable = false, length = 255) | ||
private String fileName; | ||
|
||
@Column(name = "file_type", length = 100) | ||
private String fileType; | ||
|
||
@Column(name = "file_size") | ||
private Long fileSize; | ||
|
||
@EqualsAndHashCode.Include | ||
@Column(name = "file_url", nullable = false, columnDefinition = "TEXT") | ||
private String fileUrl; | ||
|
||
@Column(name = "uploaded_at", nullable = false, updatable = false) | ||
private LocalDateTime uploadedAt; | ||
|
||
@PrePersist | ||
public void prePersist() { | ||
if (this.uploadedAt == null) { | ||
this.uploadedAt = LocalDateTime.now(); | ||
} | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
commons/src/main/java/io/flowinquiry/modules/fss/repository/EntityAttachmentRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package io.flowinquiry.modules.fss.repository; | ||
|
||
import io.flowinquiry.modules.fss.domain.EntityAttachment; | ||
import java.util.List; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import org.springframework.stereotype.Repository; | ||
|
||
@Repository | ||
public interface EntityAttachmentRepository extends JpaRepository<EntityAttachment, Long> { | ||
|
||
/** | ||
* Finds all attachments for a specific entity type and entity ID. | ||
* | ||
* @param entityType The type of entity (e.g., "team_request", "comment"). | ||
* @param entityId The ID of the entity. | ||
* @return A list of attachments for the specified entity. | ||
*/ | ||
List<EntityAttachment> findByEntityTypeAndEntityId(String entityType, Long entityId); | ||
|
||
/** | ||
* Deletes all attachments for a specific entity type and entity ID. | ||
* | ||
* @param entityType The type of entity (e.g., "team_request", "comment"). | ||
* @param entityId The ID of the entity. | ||
*/ | ||
void deleteByEntityTypeAndEntityId(String entityType, Long entityId); | ||
} |
149 changes: 149 additions & 0 deletions
149
commons/src/main/java/io/flowinquiry/modules/fss/service/EntityAttachmentService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
package io.flowinquiry.modules.fss.service; | ||
|
||
import io.flowinquiry.modules.fss.domain.EntityAttachment; | ||
import io.flowinquiry.modules.fss.repository.EntityAttachmentRepository; | ||
import io.flowinquiry.modules.fss.service.dto.EntityAttachmentDTO; | ||
import io.flowinquiry.modules.fss.service.mapper.EntityAttachmentMapper; | ||
import java.time.LocalDateTime; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
import org.springframework.web.multipart.MultipartFile; | ||
|
||
@Service | ||
public class EntityAttachmentService { | ||
|
||
private static final Logger LOG = LoggerFactory.getLogger(EntityAttachmentService.class); | ||
|
||
private final EntityAttachmentRepository entityAttachmentRepository; | ||
private final EntityAttachmentMapper entityAttachmentMapper; | ||
private final StorageService storageService; | ||
|
||
public EntityAttachmentService( | ||
EntityAttachmentRepository entityAttachmentRepository, | ||
EntityAttachmentMapper entityAttachmentMapper, | ||
StorageService storageService) { | ||
this.entityAttachmentRepository = entityAttachmentRepository; | ||
this.entityAttachmentMapper = entityAttachmentMapper; | ||
this.storageService = storageService; | ||
} | ||
|
||
/** | ||
* Uploads a single attachment and returns an unsaved EntityAttachment object. | ||
* | ||
* @param entityType The type of entity (e.g., "team_request", "comment"). | ||
* @param entityId The ID of the entity. | ||
* @param file The file to upload. | ||
* @return An unsaved EntityAttachment object. | ||
* @throws Exception If file storage fails or the file is empty. | ||
*/ | ||
private EntityAttachment createAttachment(String entityType, Long entityId, MultipartFile file) | ||
throws Exception { | ||
if (file.isEmpty()) { | ||
throw new IllegalArgumentException("File cannot be empty."); | ||
} | ||
|
||
// Store the file and get its URL | ||
String fileUrl = | ||
storageService.uploadFile( | ||
StorageService.ATTACHMENTS, | ||
file.getOriginalFilename(), | ||
file.getInputStream()); | ||
|
||
// Create the attachment entity | ||
EntityAttachment attachment = new EntityAttachment(); | ||
attachment.setEntityType(entityType); | ||
attachment.setEntityId(entityId); | ||
attachment.setFileName(file.getOriginalFilename()); | ||
attachment.setFileType(file.getContentType()); | ||
attachment.setFileSize(file.getSize()); | ||
attachment.setFileUrl(fileUrl); | ||
attachment.setUploadedAt(LocalDateTime.now()); | ||
|
||
return attachment; | ||
} | ||
|
||
/** | ||
* Uploads multiple attachments and associates them with a specific entity using batch insert. | ||
* | ||
* @param entityType The type of entity (e.g., "team_request", "comment"). | ||
* @param entityId The ID of the entity. | ||
* @param files The list of files to upload. | ||
* @return A list of saved EntityAttachment objects. | ||
* @throws Exception If any file storage operation fails. | ||
*/ | ||
@Transactional | ||
public List<EntityAttachment> uploadAttachments( | ||
String entityType, Long entityId, MultipartFile[] files) throws Exception { | ||
if (files == null || files.length == 0) { | ||
throw new IllegalArgumentException("File list cannot be empty."); | ||
} | ||
|
||
List<EntityAttachment> attachments = new ArrayList<>(); | ||
for (MultipartFile file : files) { | ||
attachments.add(createAttachment(entityType, entityId, file)); | ||
} | ||
|
||
// Perform batch insert for all attachments | ||
return entityAttachmentRepository.saveAll(attachments); | ||
} | ||
|
||
/** | ||
* Retrieves all attachments associated with a specific entity. | ||
* | ||
* @param entityType The type of entity (e.g., "team_request", "comment"). | ||
* @param entityId The ID of the entity. | ||
* @return A list of attachments for the entity. | ||
*/ | ||
public List<EntityAttachmentDTO> getAttachments(String entityType, Long entityId) { | ||
return entityAttachmentMapper.toDtoList( | ||
entityAttachmentRepository.findByEntityTypeAndEntityId(entityType, entityId)); | ||
} | ||
|
||
/** | ||
* Deletes all attachments associated with a specific entity. | ||
* | ||
* @param entityType The type of entity (e.g., "team_request", "comment"). | ||
* @param entityId The ID of the entity. | ||
*/ | ||
public void deleteAttachments(String entityType, Long entityId) throws Exception { | ||
List<EntityAttachment> attachments = | ||
entityAttachmentRepository.findByEntityTypeAndEntityId(entityType, entityId); | ||
|
||
for (EntityAttachment attachment : attachments) { | ||
if (attachment.getFileUrl() != null) { | ||
storageService.deleteFile(attachment.getFileUrl()); | ||
} | ||
} | ||
|
||
// Delete the attachment records from the database | ||
entityAttachmentRepository.deleteAll(attachments); | ||
} | ||
|
||
/** | ||
* Deletes an attachment by its ID. If the attachment does not exist, it silently ignores the | ||
* operation. | ||
* | ||
* @param attachmentId The ID of the attachment to delete. | ||
*/ | ||
@Transactional | ||
public void deleteAttachment(Long attachmentId) { | ||
entityAttachmentRepository | ||
.findById(attachmentId) | ||
.ifPresent( | ||
attachment -> { | ||
if (attachment.getFileUrl() != null) { | ||
try { | ||
storageService.deleteFile(attachment.getFileUrl()); | ||
} catch (Exception e) { | ||
LOG.error("Can not delete file {}", attachment.getFileUrl(), e); | ||
} | ||
} | ||
|
||
entityAttachmentRepository.deleteById(attachmentId); | ||
}); | ||
} | ||
} |
Oops, something went wrong.