Skip to content

Commit 83da02e

Browse files
committed
Refactor attachments
1 parent 2de95b5 commit 83da02e

File tree

10 files changed

+92
-28
lines changed

10 files changed

+92
-28
lines changed

foxogram-api/src/main/java/su/foxogram/controllers/MessagesController.java

+2-4
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,7 @@ public List<MessageDTO> getMessages(@RequestAttribute(value = AttributesConstant
5555
@Operation(summary = "Get message")
5656
@GetMapping("/channel/{id}/{messageId}")
5757
public MessageDTO getMessage(@RequestAttribute(value = AttributesConstants.CHANNEL) Channel channel, @PathVariable long id, @PathVariable long messageId) throws MessageNotFoundException {
58-
Message message = messagesService.getMessage(messageId, channel);
59-
60-
return new MessageDTO(message);
58+
return messagesService.getMessage(messageId, channel);
6159
}
6260

6361
@Operation(summary = "Create message")
@@ -69,7 +67,7 @@ public MessageDTO createMessage(@RequestAttribute(value = AttributesConstants.US
6967

7068
Message message = messagesService.addMessage(channel, user, body);
7169

72-
return new MessageDTO(message);
70+
return new MessageDTO(message, null);
7371
}
7472

7573
@Operation(summary = "Delete message")

foxogram-common/src/main/java/su/foxogram/dtos/api/response/ChannelDTO.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public ChannelDTO(Channel channel, Message lastMessage) {
4141
this.memberCount = channel.getMembers().size();
4242
}
4343
if (lastMessage != null) {
44-
this.lastMessage = new MessageDTO(lastMessage);
44+
this.lastMessage = new MessageDTO(lastMessage, null);
4545
}
4646
this.owner = new UserDTO(channel.getOwner(), null, false, false);
4747
this.createdAt = channel.getCreatedAt();

foxogram-common/src/main/java/su/foxogram/dtos/api/response/MessageDTO.java

+5-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import io.swagger.v3.oas.annotations.media.Schema;
44
import lombok.Getter;
55
import lombok.Setter;
6+
import su.foxogram.models.Attachment;
67
import su.foxogram.models.Message;
78

89
import java.util.List;
@@ -20,16 +21,17 @@ public class MessageDTO {
2021

2122
private ChannelDTO channel;
2223

23-
private List<String> attachments;
24+
private List<?> attachments;
2425

2526
private long createdAt;
2627

27-
public MessageDTO(Message message) {
28+
public MessageDTO(Message message, List<Attachment> attachments) {
2829
this.id = message.getId();
2930
this.content = message.getContent();
3031
this.author = new MemberDTO(message.getAuthor(), false);
3132
this.channel = new ChannelDTO(message.getChannel(), null);
32-
this.attachments = message.getAttachments();
33+
if (attachments != null) this.attachments = attachments;
34+
else this.attachments = message.getAttachments();
3335
this.createdAt = message.getTimestamp();
3436
}
3537
}

foxogram-common/src/main/java/su/foxogram/dtos/api/response/MessagesDTO.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class MessagesDTO {
1616

1717
public MessagesDTO(List<Message> messages) {
1818
for (Message message : messages) {
19-
this.messages.add(new MessageDTO(message));
19+
this.messages.add(new MessageDTO(message, null));
2020
}
2121
}
2222
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package su.foxogram.models;
2+
3+
import jakarta.persistence.*;
4+
import lombok.Getter;
5+
import lombok.Setter;
6+
7+
@Entity
8+
@Getter
9+
@Setter
10+
@Table(name = "attachments", indexes = {
11+
@Index(name = "idx_attachment_id", columnList = "id", unique = true)
12+
})
13+
public class Attachment {
14+
15+
@Id
16+
public String id;
17+
18+
@Column()
19+
public String filename;
20+
21+
@Column()
22+
public String contentType;
23+
24+
@Column()
25+
public long flags;
26+
27+
public Attachment() {
28+
}
29+
30+
public Attachment(String id, String filename, String contentType, long flags) {
31+
this.id = id;
32+
this.filename = filename;
33+
this.contentType = contentType;
34+
this.flags = flags;
35+
}
36+
}

foxogram-common/src/main/java/su/foxogram/models/Message.java

-2
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ public class Message {
2727
@Column()
2828
public long timestamp;
2929

30-
@ElementCollection(targetClass = String.class, fetch = FetchType.EAGER)
31-
@CollectionTable(name = "attachments", joinColumns = @JoinColumn(name = "message_id"))
3230
@Column()
3331
public List<String> attachments;
3432

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package su.foxogram.repositories;
2+
3+
import jakarta.validation.constraints.NotNull;
4+
import org.springframework.data.repository.CrudRepository;
5+
import org.springframework.stereotype.Repository;
6+
import su.foxogram.models.Attachment;
7+
8+
@Repository
9+
public interface AttachmentRepository extends CrudRepository<Attachment, Long> {
10+
11+
Attachment findById(String id);
12+
13+
@Override
14+
void delete(@NotNull Attachment attachment);
15+
}

foxogram-common/src/main/java/su/foxogram/services/ChannelsService.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ private void changeIcon(Channel channel, MultipartFile icon) throws UploadFailed
142142
String hash;
143143

144144
try {
145-
hash = storageService.uploadToMinio(icon, StorageConstants.AVATARS_BUCKET);
145+
hash = storageService.uploadIdentityImage(icon, StorageConstants.AVATARS_BUCKET);
146146
} catch (Exception e) {
147147
throw new UploadFailedException();
148148
}

foxogram-common/src/main/java/su/foxogram/services/MessagesService.java

+20-12
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,8 @@
1313
import su.foxogram.exceptions.cdn.UploadFailedException;
1414
import su.foxogram.exceptions.member.MissingPermissionsException;
1515
import su.foxogram.exceptions.message.MessageNotFoundException;
16-
import su.foxogram.models.Channel;
17-
import su.foxogram.models.Member;
18-
import su.foxogram.models.Message;
19-
import su.foxogram.models.User;
16+
import su.foxogram.models.*;
17+
import su.foxogram.repositories.AttachmentRepository;
2018
import su.foxogram.repositories.ChannelRepository;
2119
import su.foxogram.repositories.MemberRepository;
2220
import su.foxogram.repositories.MessageRepository;
@@ -40,13 +38,16 @@ public class MessagesService {
4038

4139
private final MemberRepository memberRepository;
4240

41+
private final AttachmentRepository attachmentRepository;
42+
4343
@Autowired
44-
public MessagesService(MessageRepository messageRepository, StorageService storageService, RabbitService rabbitService, ChannelRepository channelRepository, MemberRepository memberRepository) {
44+
public MessagesService(MessageRepository messageRepository, StorageService storageService, RabbitService rabbitService, ChannelRepository channelRepository, MemberRepository memberRepository, AttachmentRepository attachmentRepository) {
4545
this.messageRepository = messageRepository;
4646
this.storageService = storageService;
4747
this.rabbitService = rabbitService;
4848
this.channelRepository = channelRepository;
4949
this.memberRepository = memberRepository;
50+
this.attachmentRepository = attachmentRepository;
5051
}
5152

5253
public List<MessageDTO> getMessages(long before, int limit, Channel channel) {
@@ -55,18 +56,25 @@ public List<MessageDTO> getMessages(long before, int limit, Channel channel) {
5556
log.info("Messages ({}, {}) in channel ({}) found successfully", limit, before, channel.getId());
5657

5758
return messagesArray.reversed().stream()
58-
.map(MessageDTO::new)
59+
.map(message -> {
60+
List<Attachment> attachments = new ArrayList<>();
61+
message.getAttachments().forEach(attachment -> attachments.add(attachmentRepository.findById(attachment)));
62+
return new MessageDTO(message, attachments);
63+
})
5964
.collect(Collectors.toList());
6065
}
6166

62-
public Message getMessage(long id, Channel channel) throws MessageNotFoundException {
67+
public MessageDTO getMessage(long id, Channel channel) throws MessageNotFoundException {
6368
Message message = messageRepository.findByChannelAndId(channel, id);
6469

6570
if (message == null) throw new MessageNotFoundException();
6671

72+
List<Attachment> attachments = new ArrayList<>();
73+
message.getAttachments().forEach(attachment -> attachments.add(attachmentRepository.findById(attachment)));
74+
6775
log.info("Message ({}) in channel ({}) found successfully", id, channel.getId());
6876

69-
return message;
77+
return new MessageDTO(message, attachments);
7078
}
7179

7280
public Message addMessage(Channel channel, User user, MessageCreateDTO body) throws UploadFailedException, JsonProcessingException {
@@ -78,7 +86,7 @@ public Message addMessage(Channel channel, User user, MessageCreateDTO body) thr
7886
uploadedAttachments = body.getAttachments().stream()
7987
.map(attachment -> {
8088
try {
81-
return uploadAttachment(attachment);
89+
return uploadAttachment(attachment).getId();
8290
} catch (UploadFailedException e) {
8391
throw new RuntimeException(e);
8492
}
@@ -92,7 +100,7 @@ public Message addMessage(Channel channel, User user, MessageCreateDTO body) thr
92100
Message message = new Message(channel, body.getContent(), member, uploadedAttachments);
93101
messageRepository.save(message);
94102

95-
rabbitService.send(getRecipients(channel), new MessageDTO(message), GatewayConstants.Event.MESSAGE_CREATE.getValue());
103+
rabbitService.send(getRecipients(channel), new MessageDTO(message, null), GatewayConstants.Event.MESSAGE_CREATE.getValue());
96104
log.info("Message ({}) to channel ({}) created successfully", message.getId(), channel.getId());
97105

98106
return message;
@@ -120,13 +128,13 @@ public Message editMessage(long id, Channel channel, Member member, MessageCreat
120128
message.setContent(content);
121129
messageRepository.save(message);
122130

123-
rabbitService.send(getRecipients(channel), new MessageDTO(message), GatewayConstants.Event.MESSAGE_UPDATE.getValue());
131+
rabbitService.send(getRecipients(channel), new MessageDTO(message, null), GatewayConstants.Event.MESSAGE_UPDATE.getValue());
124132
log.info("Message ({}) in channel ({}) edited successfully", id, channel.getId());
125133

126134
return message;
127135
}
128136

129-
private String uploadAttachment(MultipartFile attachment) throws UploadFailedException {
137+
private Attachment uploadAttachment(MultipartFile attachment) throws UploadFailedException {
130138
try {
131139
return storageService.uploadToMinio(attachment, StorageConstants.ATTACHMENTS_BUCKET);
132140
} catch (Exception e) {

foxogram-common/src/main/java/su/foxogram/services/StorageService.java

+11-4
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@
1010
import org.springframework.stereotype.Service;
1111
import org.springframework.web.multipart.MultipartFile;
1212
import su.foxogram.exceptions.cdn.InvalidFileFormatException;
13+
import su.foxogram.models.Attachment;
1314
import su.foxogram.models.Channel;
1415
import su.foxogram.models.Message;
1516
import su.foxogram.models.User;
17+
import su.foxogram.repositories.AttachmentRepository;
1618
import su.foxogram.repositories.ChannelRepository;
1719
import su.foxogram.repositories.MessageRepository;
1820
import su.foxogram.repositories.UserRepository;
@@ -47,12 +49,15 @@ public class StorageService {
4749

4850
private final MessageRepository messageRepository;
4951

52+
private final AttachmentRepository attachmentRepository;
53+
5054
@Autowired
51-
public StorageService(MinioAsyncClient minioClient, UserRepository userRepository, ChannelRepository channelRepository, MessageRepository messageRepository) {
55+
public StorageService(MinioAsyncClient minioClient, UserRepository userRepository, ChannelRepository channelRepository, MessageRepository messageRepository, AttachmentRepository attachmentRepository) {
5256
this.minioClient = minioClient;
5357
this.userRepository = userRepository;
5458
this.channelRepository = channelRepository;
5559
this.messageRepository = messageRepository;
60+
this.attachmentRepository = attachmentRepository;
5661
}
5762

5863
private static String getFileHash(byte[] imageBytes) throws NoSuchAlgorithmException {
@@ -67,21 +72,23 @@ private static String getFileHash(byte[] imageBytes) throws NoSuchAlgorithmExcep
6772
return hexString.toString();
6873
}
6974

70-
public String uploadToMinio(MultipartFile file, String bucketName) throws RuntimeException, IOException, ExecutionException, InterruptedException, NoSuchAlgorithmException {
75+
public Attachment uploadToMinio(MultipartFile file, String bucketName) throws RuntimeException, IOException, ExecutionException, InterruptedException, NoSuchAlgorithmException {
7176
byte[] byteArray = file.getBytes();
7277
FileData fileData = new FileData(file);
7378

7479
log.info("Uploading file ({}, {}, {}, {}) to bucket ({})", fileData.getName(), fileData.getExtension(), fileData.getType(), fileData.getContentType(), bucketName);
7580

7681
if (isHashExists(fileData.getHash())) {
7782
log.info("Duplicate file ({}) found. Skipping upload...", fileData.getHash());
78-
return fileData.getHash();
83+
return new Attachment(fileData.getHash(), fileData.getName(), fileData.getContentType(), 0);
7984
}
8085

8186
ensureBucketExists(bucketName);
8287
uploadFile(byteArray, fileData, bucketName);
8388

84-
return fileData.getHash();
89+
Attachment attachment = new Attachment(fileData.getHash(), fileData.getName(), fileData.getContentType(), 0);
90+
attachmentRepository.save(attachment);
91+
return attachment;
8592
}
8693

8794
public String uploadIdentityImage(MultipartFile file, String bucketName) throws IOException, NoSuchAlgorithmException, ExecutionException, InterruptedException, InvalidFileFormatException {

0 commit comments

Comments
 (0)